diff --git a/.DS_Store b/.DS_Store index 4ca6959..d8e3d57 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..21edbbf --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +MONGODB_URI=mongo_url_here +QDRANT_HOST=qdrant +QDRANT_PORT=6333 +CLEARML_API_ACCESS_KEY=access_key_here +CLEARML_API_SECRET_KEY=secret_key_here +HF_TOKEN=hf_token_here \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7eb7b75..0194a3b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,6 @@ models/ # Logs *.log -clearml.conf \ No newline at end of file +clearml.conf + +app/configs/keys.yaml \ No newline at end of file diff --git a/README.md b/README.md index d425930..27c2614 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,27 @@ # ROS2 RAG System +### Team Member IDs +- GitHub IDs: [Adamay Mann](https://github.com/mannadamay12), [Dongkyu Cho](https://github.com/umamicode) +- HuggingFace IDs: [mannadamay12](https://huggingface.co/mannadamay12), [sqvareinch](https://huggingface.co/sqvareinch) + +A Retrieval Augmented Generation (RAG) system designed to assist ROS2 robotics developers with navigation stack development. The system provides specific answers and code examples for robotics development queries across ros2, nav2, moveit2, and gazebo subdomains. [Application-rag-ros2](https://huggingface.co/spaces/mannadamay12/rag-ros2) +![Architecture](assets/architecture.png) + +## Features +- Multi-source data ingestion (documentation, GitHub, tutorials) +- Vector similarity search for relevant context retrieval +- Fine-tuned language models available on HuggingFace +- Interactive query interface with pre-populated robotics questions +- Docker containerization for easy deployment + ## Environment Setup -This project uses Docker Compose to set up the development environment. +1. This project uses Docker Compose to set up the development environment. +2. Virutal env and requirements can be pulled in to run locally +``` +python3.9 -m venv rag-venv +pip install -r requirements.txt +``` ### Prerequisites - Docker @@ -19,6 +38,144 @@ This project uses Docker Compose to set up the development environment. - Qdrant: Vector search engine - ClearML: Orchestrator and experiment tracking system -### Team IDs -- GitHub IDs: [mannadamay12, umamicode] -- HuggingFace IDs: [mannadamay12, sqvareinch] \ No newline at end of file +### Docker ps +![PS image](assets/docker-ps.png) + +### Model Cards (fine-tuned) on hugging face +![Model Cards](assets/Model-card.png) + +## Data Collection Milestone +1. Scraping of documentation urls for ros2, nav2, moveit2, gazeob +2. Getting GitHub repos(although everything is covered in documention) and youtube tutorial transcripts +3. Mongodb store for database collection of variuos documents +4. Clear orchestration using clearml tasks and pipelines to track progress of ingestion +5. Base crawler and scraper to extract data from provided `sources.yaml` + +![ingest urls](assets/etl-ingest.png) + + +## Featurization Pipelines Milestone +1. Vector database creation using qdrant. +2. Use sentence transformers to create chunks and store the vector database in qdrant client. +3. Simulataneously mark in mongodb collections if the current document has been feature extracted. +4. Use clearml orchestrator to track progress. +> 🤖 Please have a look at *'notebooks/04_llama_rag.ipynb'* for a detailed understanding of this section. + +After the data is prepared, we implemented a vectorDB using [Chroma](https://www.trychroma.com/) and [Qdrant](https://qdrant.tech/). For our pipeline, we used Chroma owing to its customization features. + +For featurization, we used the pre-trained [](https://huggingface.co/hkunlp/instructor-base) model as the embedding model. Using the embedding model, we featurized the documents and launched a Chroma database for later use. At this point, the RAG system is ready for use. + + +*** +## Finetuning Milestone + +For the fine-tuning milestone, we have focused on two sub-objectives. + +1. Generate Fine-tuning Data using Large Language Models + +2. Parameter-efficient Fine-tuning with limited GPU resources. + +### 1. Generate Fine-tuning Data using Large Language Models +> 🤖 Please refer to *'notebooks/02_finetuning_data_generation .ipynb'* for a detailed understanding of how we augmented data using LLMs. + +Our fine-tuning data, consists of 1500+ pairs of question-answer pairs generated from the Ros2 documentation. In specific, we used a pre-trained LLM (e.g., LLama-3.1-70B) to select informative Q&A pairs. + +Below are samples of the Q&A pairs we have generated. +``` +{'question': 'What is the recommended prerequisite for installing the webots_ros2 package?', 'answer': 'Understanding basic ROS principles covered in the beginner Tutorials, particularly Creating a workspace and Creating a package.'}, +{'question': 'How do you install the webots_ros2 package from the latest up-to-date sources from Github?', 'answer': 'By running the command "git clone --recurse-submodules src/webots_ros2" in a terminal.'}, +{'question': 'What is the purpose of the webots_ros2 package?', 'answer': 'The webots_ros2 package provides an interface between ROS 2 and Webots.'}, +{'question': 'What is the environment variable used to specify the location of Webots?', 'answer': 'ROS2_WEBOTS_HOME'}, +{'question': "What happens if Webots couldn't be found in the default installation paths?", 'answer': 'webots_ros2 will show a window offering the automatic installation of the latest compatible version of Webots.'}, +{'question': 'How do you launch the webots_ros2_universal_robot example?', 'answer': 'By running the command "ros2 launch webots_ros2_universal_robot multirobot_launch.py"'}, +{'question': 'What is the command to install the package dependencies for webots_ros2?', 'answer': 'sudo apt install python3-pip python3-rosdep python3-colcon-common-extensions'}, +{'question': 'What is the command to build the package using colcon?', 'answer': 'colcon build'}, +{'question': 'What is the command to source the ROS 2 environment?', 'answer': 'source /opt/ros/jazzy/setup.bash'}, +{'question': 'What is the command to set the WEBOTS_HOME environment variable?', 'answer': 'export WEBOTS_HOME=/usr/local/webots'} +``` + + +A key obstacle in generating fine-tuning data was to find a reliable LLM that could generate data with consistent formatting. For this, we tested 5 models of different sizes (1B, 3B, 8B, 13B, 70B). However, we found that smaller models tend to face issues in generating their responses in a consistent format, which is critical for parsing. Hence, we used the [Llama-3.1-70B-Instruct](https://huggingface.co/meta-llama/Llama-3.1-70B-Instruct) model using quantization techniques for acceleration. + +The generated Question-Answer pairs were then parsed, and then converted into the [ShareGPT](https://www.reddit.com/r/LocalLLaMA/comments/1ail8jr/qlora_with_sharegpt_and_chatml_template_ready_to/) format. +``` +{"role": "system", "content": "You are an helpful agent."}, +{"role": "user", "content": row['question']}, +{"role": "assistant", "content": row['answer']} +``` + + + + +### 2. Parameter-efficient Fine-tuning with limited GPU resources. +> 🤖 Please refer to *'notebooks/03_llama_finetuning.ipynb'* for a detailed report of the finetuning process. + +Using the generated data, we fine-tuned our Language Model. Specifically, we used two types of models. +1. [LLama-3.2-1B-Instruct](https://huggingface.co/meta-llama/Llama-3.2-1B-Instruct) +2. [LLama-3.2-3B-Instruct](https://huggingface.co/meta-llama/Llama-3.2-3B-Instruct) + +While the two are lighter models compared to the state-of-the-art models, it still requires enormous GPU resources for fine-tuning. Hence, we adopted recent PEFT (Parameter-Efficient Fine Tuning) techniques for efficient fine-tuning. + +Specifically, we used a technique called [LoRA](https://arxiv.org/abs/2106.09685), which uses low-rank linear layers to fine-tune a pre-trained model efficiently. On top of that, we used quantization techniques to make the model sparse, and hence lighter. + +``` +peft_config = LoraConfig( + r=16, + lora_alpha=32, + lora_dropout=0.05, + bias="none", + task_type="CAUSAL_LM", + target_modules=modules +) +``` + +Using LoRA, we fine-tuned the model. We purchased a Google COLAB Pro Version. We trained the model using a light T4 GPU. + +``` +training_args= TrainingArguments( + #output_dir= "./results", + output_dir= "/content/drive/MyDrive/data/output", + per_device_train_batch_size= 4, + per_device_eval_batch_size= 4, + gradient_accumulation_steps=2, # + optim="paged_adamw_32bit", + num_train_epochs= 3, + learning_rate= 2e-5, + logging_dir="/content/drive/MyDrive/data/logs", + logging_steps=10, + report_to="none" +) + + +trainer = SFTTrainer( + model=model, + train_dataset=dataset, + peft_config=peft_config, + max_seq_length= 512, + dataset_text_field="text", + tokenizer=tokenizer, + args= training_args, + packing= False, +) + +trainer.train() +``` + +The fine-tuned models are publicly available on [Huggingface](https://huggingface.co/sqvareinch). + +> 🤖 For use the fine-tuned models, please have a look at the *'05_using-finetuned-model.ipynb'*. + +*** + +## Deploying the App Milestone + +> ⚠️ **Important Note:** +> +> Since this application uses Hugging Face Spaces and ZeroGPU for model inference, it is subject to usage quotas: +> - The app may become temporarily unavailable when quota limits are reached +> - You may need to wait a few minutes before trying again + +### Example prompts as per project description +![dropdown](assets/dropdown.png) +![Example 1](assets/Example-prompt-1.png) +![Example 2](assets/Example-prompt-2.png) diff --git a/app/Dockerfile b/app/Dockerfile index 9349fc2..bf739b7 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -5,6 +5,19 @@ WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt +# Add Jupyter configuration +RUN mkdir -p /root/.jupyter +COPY jupyter_notebook_config.py /root/.jupyter/ + COPY . . -CMD ["python", "main.py"] \ No newline at end of file +# Expose Jupyter port +EXPOSE 8888 + +# Update CMD to run Jupyter by default +CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root"] + +RUN apt-get update && apt-get install -y \ + git \ + curl \ + && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/configs/api_keys.yaml.example b/app/configs/api_keys.yaml.example new file mode 100644 index 0000000..3e00270 --- /dev/null +++ b/app/configs/api_keys.yaml.example @@ -0,0 +1,4 @@ +github: + access_token: "your_api_key" +youtube: + api_key: "your_api key" \ No newline at end of file diff --git a/app/configs/sources.yaml b/app/configs/sources.yaml new file mode 100644 index 0000000..04e3d71 --- /dev/null +++ b/app/configs/sources.yaml @@ -0,0 +1,62 @@ +sources: + documentation: + ros2: + base_url: "https://docs.ros.org/en/jazzy/" + sections: + - "Installation.html" + - "Tutorials.html" + - "How-To-Guides.html" + - "Concepts.html" + version: "jazzy" + nav2: + base_url: "https://docs.nav2.org/" + sections: + - "getting_started/index.html" + - "development_guides/index.html" + - "concepts/index.html" + - "setup_guides/index.html" + - "tutorials/index.html" + - "plugin_tutorials/index.html" + - "configuration/index.html" + - "tuning/index.html" + - "behavior_trees/index.html" + - "commander_api/index.html" + version: "latest" + moveit2: + base_url: "https://moveit.picknik.ai/main/doc" + sections: + - "tutorials/tutorials.html" + - "examples/examples.html" + - "concepts/concepts.html" + - "how_to_guides/how_to_guides.html" + version: "main" + gazebo: + base_url: "https://gazebosim.org/docs/latest" + sections: + - "getstarted" + - "tutorials" + - "ros_installation" + - "architecture" + version: "latest" + + # github_repos: + # ros2: + # - name: "ros2/ros2" + # url: "https://github.com/ros2/ros2" + # branches: ["humble", "foxy"] # LTS releases + # - name: "ros2/examples" + # url: "https://github.com/ros2/examples" + # branches: ["humble", "foxy"] + # - name: "ros2/documentation" + # url: "https://github.com/ros2/documentation" + # branches: ["humble", "foxy"] + + youtube_playlists: + ros2: + - channel_id: "UCK8Y_nwY_L1DaHXrZUUozAg" # ROS2 Official + playlists: + - "PLNw1_R4SfJQf_i5un9AGGj1jmqWJ4yE4i" # ROS2 Tutorials Playlist + - "PLNw1_R4SfJQfQUVT6TJAXcv2yIQjzNHXz" # ROS2 Demos + - channel_id: "UCt6Lag-vv25fSpX_yf2Rs1Q" # The Construct + playlists: + - "PLK0b4e05LnzZpAM3NxXXUUNfbqC2YLIGq" # ROS2 Basics Course \ No newline at end of file diff --git a/app/etl/__init__.py b/app/etl/__init__.py new file mode 100644 index 0000000..166ce0b --- /dev/null +++ b/app/etl/__init__.py @@ -0,0 +1 @@ +# Empty file to make the directory a Python package \ No newline at end of file diff --git a/app/etl/extract/__init__.py b/app/etl/extract/__init__.py new file mode 100644 index 0000000..166ce0b --- /dev/null +++ b/app/etl/extract/__init__.py @@ -0,0 +1 @@ +# Empty file to make the directory a Python package \ No newline at end of file diff --git a/app/etl/extract/doc_extract.py b/app/etl/extract/doc_extract.py new file mode 100644 index 0000000..9985859 --- /dev/null +++ b/app/etl/extract/doc_extract.py @@ -0,0 +1,147 @@ +from playwright.async_api import async_playwright +from bs4 import BeautifulSoup +from pathlib import Path +from typing import Dict, Any, List, Set +from loguru import logger +import uuid +import json +import asyncio +from datetime import datetime +from urllib.parse import urljoin, urlparse + +class DocumentationExtractor: + def __init__(self): + self.visited_urls: Set[str] = set() + self.browser = None + self.context = None + + async def _init_browser(self): + if not self.browser: + playwright = await async_playwright().start() + self.browser = await playwright.chromium.launch(headless=True) + self.context = await self.browser.new_context() + + async def _get_page_content(self, url: str) -> Dict[str, Any]: + await self._init_browser() + try: + page = await self.context.new_page() + await page.goto(url, wait_until='networkidle') + html = await page.content() + await page.close() + + soup = BeautifulSoup(html, 'html.parser') + return { + 'soup': soup, + 'url': url + } + except Exception as e: + logger.error(f"Error fetching {url}: {str(e)}") + return None + + def _extract_content(self, soup: BeautifulSoup) -> Dict[str, Any]: + # Try multiple possible content containers + main_content = ( + soup.find('div', class_='content') or + soup.find('article') or + soup.find('main') or + soup.find('div', class_='document') + ) + + if not main_content: + return None + + title = soup.find('h1') + title_text = title.get_text(strip=True) if title else '' + + sections = [] + current_section = {'heading': '', 'content': ''} + for element in main_content.find_all(['h2', 'h3', 'p', 'ul', 'ol']): + if element.name in ['h2', 'h3']: + if current_section['content']: + sections.append(current_section) + current_section = { + 'heading': element.get_text(strip=True), + 'content': '' + } + else: + current_section['content'] += element.get_text(strip=True) + '\n' + + if current_section['content']: + sections.append(current_section) + + code_blocks = [] + for pre in main_content.find_all('pre'): + code = self._clean_code_block(pre) + if code: + code_blocks.append(code) + + return { + 'title': title_text, + 'sections': sections, + 'code_blocks': code_blocks + } + + def _parse_code_block(self, pre: BeautifulSoup) -> Dict[str, str]: + try: + language = 'unknown' + if pre.parent.get('class'): + for cls in pre.parent['class']: + if cls.startswith(('language-', 'highlight-')): + language = cls.split('-')[1] + break + + code = pre.get_text(strip=True) + filename = '' + if code_ref := pre.find_previous('code', class_='literal'): + filename = code_ref.get_text(strip=True) + + return { + 'language': language, + 'code': code, + 'filename': filename + } + except Exception as e: + logger.error(f"Error parsing code block: {str(e)}") + return None + + async def extract_docs(self, base_url: str, sections: List[str], subdomain: str, version: str) -> List[Dict[str, Any]]: + docs = [] + try: + for section in sections: + url = urljoin(base_url + '/', section) + if url in self.visited_urls: + continue + + self.visited_urls.add(url) + page_data = await self._get_page_content(url) + + if not page_data: + continue + + content = self._extract_content(page_data['soup']) + if content: + doc = { + "id": str(uuid.uuid4()), + "source": { + "url": url, + "version": version + }, + "content": content, + "metadata": { + "section": section, + "subdomain": subdomain, + "timestamp": datetime.now().isoformat() + } + } + docs.append(doc) + + await asyncio.sleep(1) # Rate limiting + + except Exception as e: + logger.error(f"Error in extract_docs: {str(e)}") + + return docs + + async def close(self): + if self.browser: + await self.browser.close() \ No newline at end of file diff --git a/app/etl/extract/github_extract.py b/app/etl/extract/github_extract.py new file mode 100644 index 0000000..50d4b9a --- /dev/null +++ b/app/etl/extract/github_extract.py @@ -0,0 +1,55 @@ +from github import Github +from typing import Dict, Any, List +import base64 +from datetime import datetime +import uuid +from loguru import logger + +class GitHubExtractor: + def __init__(self, access_token: str = None): + self.github = Github(access_token) + + def extract_repo_content(self, repo_name: str, branch: str) -> List[Dict[str, Any]]: + try: + repo = self.github.get_repo(repo_name) + contents = [] + + for content in repo.get_contents("", ref=branch): + if content.type == "file" and content.name.endswith(('.md', '.rst')): + doc = self._process_file(content, repo_name, branch) + if doc: + contents.append(doc) + + return contents + + except Exception as e: + logger.error(f"Error extracting from {repo_name}: {str(e)}") + return [] + + def _process_file(self, content, repo_name: str, branch: str) -> Dict[str, Any]: + try: + file_content = base64.b64decode(content.content).decode('utf-8') + + return { + "id": str(uuid.uuid4()), + "type": "github_documentation", + "subdomain": repo_name.split('/')[1], + "source": { + "url": content.html_url, + "repo": repo_name, + "branch": branch, + "path": content.path, + "last_updated": datetime.now().isoformat() + }, + "content": { + "title": content.name, + "body": file_content + }, + "metadata": { + "crawl_timestamp": datetime.now().isoformat(), + "size": content.size + } + } + except Exception as e: + logger.error(f"Error processing file {content.path}: {str(e)}") + return None \ No newline at end of file diff --git a/app/etl/extract/test.ipynb b/app/etl/extract/test.ipynb new file mode 100644 index 0000000..e8101cd --- /dev/null +++ b/app/etl/extract/test.ipynb @@ -0,0 +1,198629 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append('/Users/ad12/Documents/Develop/ros2-rag-project') # or the path to your project root" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "from extract.doc_extract import DocumentationExtractor" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2024-12-06 14:41:04.171\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 759 links in section getting_started/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.267\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#configuring-nav2-costmap-2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.334\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#rpp-new-optional-interpolate-curvature-after-goal-behavior-and-fix-conflict-between-use-rotate-to-heading-and-allow-reversing\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.403\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#including-new-rotation-shim-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.588\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#why-use-a-dev-container\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.703\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#setup-your-environment-variables\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.770\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.830\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#install-stvl\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:04.887\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-nav2-loopback-simulator\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.087\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.211\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#common-sensor-messages\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.266\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#control-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.317\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#new-parameter-use-final-approach-orientation-for-the-3-2d-planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.375\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/RemovePassedGoals.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.424\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html#navigation2-architectural-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.693\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-bt-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.775\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#run-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.828\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/path_dist.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.890\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#new-costmap-layer\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:05.954\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.154\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/robots.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.276\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-navfn.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.343\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#help\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.393\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html#simple-smoother-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.447\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#the-costmap-activation-fails-when-required-transforms-are-not-available\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.499\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputePathThroughPoses.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.668\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#condition-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.781\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#behavior-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.841\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.916\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:06.980\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#velocity-smoother-applies-deceleration-when-timeout\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.045\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.209\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#introduction-of-costmapupdate-msg\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.301\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#other-pages-we-d-love-to-offer\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.365\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.456\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#prefer-forward-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.549\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.732\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#mppi-controller-addition-of-acceleration-constraints\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.803\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.848\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#general\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:07.926\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/collision_monitor/configuring-collision-detector-node.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.024\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#smacplanner2d-navfn-and-theta-fix-small-path-corner-cases\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.104\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-follow-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.276\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#costmap2d-ros-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.347\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.450\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#removed-global-map-topic-from-costmap-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.493\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.558\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#enable-keepout-filter\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.779\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.848\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#costmap-filter-info-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:08.984\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html#humble-roadmap\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.047\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#id1\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.092\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#caching-obstacle-heuristic-in-smac-planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.292\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#build-run-and-verification\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.357\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#driveonheading-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.506\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#profile-from-a-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.570\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.652\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/collision_monitor/configuring-collision-monitor-node.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.841\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#preparing-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:09.899\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.033\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.090\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.181\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#navigation-subtree\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.348\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#provided-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.452\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/denoise.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.553\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#costmap-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.609\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/obstacle_footprint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.658\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#footprint-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.697\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:10.963\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#run-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.007\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#option-to-limit-velocity-through-dwb-trajectory\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.064\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/voxel.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.111\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html#using-dev-containers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.193\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.458\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#standard-time-units-in-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.528\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#robot-footprints\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.576\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#run-time-speed-up-of-smac-planner\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.635\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.686\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:11.746\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.026\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#setting-up-the-environment\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.115\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#fusing-vio-into-local-state-estimate\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.210\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.264\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.506\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.589\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-thetastar.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.636\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#fix-flickering-visualization\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.719\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#constraint-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:12.774\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#configuring-collision-monitor-with-velocitypolygon\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.022\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-thetastar.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.074\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#standardization-of-plugin-naming-with-double-colons\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.129\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#cancel-checker-interface-for-globalplanner\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.178\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.241\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/goal_dist.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.338\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#configuring-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.543\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#introduce-a-new-multi-robot-bringup-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.611\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#exporting-the-planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.666\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.771\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#mppi-acceleration\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:13.819\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/base_obstacle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.017\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#allow-multiple-goal-checkers-and-change-parameter-progress-checker-plugin-s-name-and-type\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.071\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.124\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html#smoother-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.177\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#licensing\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.266\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#ros-2\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.319\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/speed_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.369\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-btactionserver-btnavigator-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.556\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.611\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#prepare-filter-mask\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.714\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearCostmapAroundRobot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.765\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-cancel-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.807\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#action-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:14.871\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.065\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#fusing-vslam-into-global-state-estimate\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.207\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#obstacle-inflation-layer-and-path-following\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.265\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.328\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-nav2-bringup\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.378\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.672\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#id3\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.739\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.786\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.832\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#planner-plugin-selection\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.881\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#costmap-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:15.940\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#released-distribution-binaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.201\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#default-behavior-tree-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.250\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsStopped.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.305\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_through_poses_recovery.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.353\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#security\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.409\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.497\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#lifecycle-nodes-and-bond\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.647\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.700\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldAControllerRecoveryHelp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.752\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#pass-the-plugin-name-through-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.807\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.882\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-navfn.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:16.972\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.201\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.246\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#selection-of-behavior-tree-in-each-navigation-action\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.307\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#building-a-development-image\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.356\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#changes-to-map-yaml-file-path-for-map-server-node-in-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.479\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#prediction-horizon-costmap-sizing-and-offsets\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.522\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#recursive-refinement-of-smac-and-simple-smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.712\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#adding-gazebo-plugins-to-a-urdf\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.757\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#setting-up-zed-ros\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.872\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#preliminaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.920\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:17.976\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.015\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#run-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.284\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.356\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#simplechargingdock-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.410\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#configure-costmap-filter-info-publisher-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.457\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#costmaps-and-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.498\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#profile-from-a-launch-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.582\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#getting-started\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.737\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#twiststamped-default-cmdvel-change\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.859\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#setup-gazebo-world\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:18.910\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#familiarization-with-the-smoother-bt-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.007\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#robot-footprint-vs-radius\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.052\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#isbatterychargingcondition-bt-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.105\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#allow-behavior-server-plugins-to-access-the-action-result\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.262\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.310\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#rotate-in-place-behavior\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.366\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.481\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/smac/configuring-smac-hybrid.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.543\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#lifecycle-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.590\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.802\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:19.895\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/TruncatePath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.002\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#odometry\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.088\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#general-words-of-wisdom\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.150\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#action-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.328\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#smac-planner-hybrid-a-new-features\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.430\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html#iron-roadmap\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.479\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#build-instructions\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.572\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-handler\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.615\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#waypoint-following\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.840\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:20.969\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.043\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.091\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#groot-support\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.135\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#publish-collision-monitor-state\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.219\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.358\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ControllerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.402\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#from-nav2-bringup\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.454\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/DockRobot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.510\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.607\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#assistedteleop-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.703\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#smacplanner2d-and-theta-fix-goal-orientation-being-ignored\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.883\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearCostmapExceptRegion.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.938\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#opennav-coverage-project\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:21.989\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#error-codes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.048\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#visualize-behavior-trees\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.143\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#removed-use-approach-velocity-scaling-param-in-rpp\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.194\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#subtrees-obtain-shared-resources\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.394\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-collision-monitor.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.462\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#added-smoother-task-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.510\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#poseprogresschecker-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.621\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#dropping-support-for-live-groot-monitoring-of-nav2\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.667\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-thetastar.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.726\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/RateController.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:22.945\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#writing-the-urdf\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.036\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.166\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.245\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#notes-to-users\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.297\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.516\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#what-why-how\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.576\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#exploring-your-first-container\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.625\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/InitialPoseReceived.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.678\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#constrained-smoother\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.736\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-pipelinesequence\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:23.786\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#enable-denoise-layer\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.050\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#refactored-amcl-motion-models-as-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.102\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/odometry_calibration.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.156\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.208\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/DriveOnHeading.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.254\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#behaviors\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.344\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.503\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smacplannerhybrid-viz-expansions-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.550\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#simple-commander-python-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.601\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputePathToPose.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.648\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#dwb-forward-vs-reverse-pruning\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.693\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/wait_at_waypoint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.784\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:24.841\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.030\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.096\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.142\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#costmap2d-and-stvl\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.248\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.298\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/DistanceTraveled.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.352\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.561\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-rviz-plugin-for-selecting-planners-controllers-goal-checkers-progress-checkers-and-smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.624\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Smooth.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.719\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.775\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#creating-a-new-planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.823\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#interpreting-results\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:25.901\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#ackermann-motion-model\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.084\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#dynamic-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.199\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#recovery-to-behavior\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.249\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#load-save-and-loop-waypoints-from-the-nav2-panel-in-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.306\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#setup-navigation-system\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.353\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#testing-it-out\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.414\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/SingleTrigger.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.675\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/TruncatePathLocal.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.718\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.772\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#fix-costmaplayer-cleararea-invert-param-logic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.827\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#followpath-goal-checker-id-attribute\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:26.915\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#behaviortree-cpp-upgraded-to-version-4-5\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.019\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.133\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#putting-it-all-together\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.189\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#visualizations-from-docker\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.237\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#regulatedpurepursuitcontroller\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.277\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#working-with-slam\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.368\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#inflation-potential-fields\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.438\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#simulating-sensors-using-gazebo\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.640\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/build_troubleshooting_guide.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:27.696\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#setup-rviz-clicked-point\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.164\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.281\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/static.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.346\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.397\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/SpeedController.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.443\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.495\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.762\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#launch-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.820\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#what-is-a-dev-container\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.877\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#smac-planner-on-approach-to-goal-shortcutting-solutions\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.946\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#adding-gazebo-plugins-to-a-urdf\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:28.990\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#what-is-the-rotation-shim-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.076\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html#savitzky-golay-smoother-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.219\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#revamped-multirobot-bringup-and-config-files-to-use-namespaces\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.278\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.342\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/obstacle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.384\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.492\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.534\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.592\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#exporting-the-navigator-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.738\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#launch-turtlebot-3\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.792\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#recovery-action-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.912\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.959\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#added-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:29.999\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#getting-started-simplification\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.050\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ReinitializeGlobalLocalization.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.093\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.354\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.443\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-rviz-tool-for-costmap-cost-cell-inspection\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.486\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.540\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#pass-the-plugin-name-through-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.587\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldAPlannerRecoveryHelp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.627\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#how-it-works\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.868\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.921\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/BackUp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:30.962\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.015\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/RemoveInCollisionGoals.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.070\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.164\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#added-twiststamped-option-for-commands\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.338\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.396\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.442\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#specifying-a-smoother-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.539\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#changes-to-mppi-path-angle-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.588\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/UndockRobot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.639\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#rotation-shim-controller-new-parameter-rotate-to-goal-heading\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.847\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.902\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:31.949\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#configuring-rotation-shim-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.061\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#launch-nav2\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.106\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.150\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#preliminaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.200\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearEntireCostmap.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.382\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelSpin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.428\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#controllers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.528\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#setting-up-the-zed-x-camera\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.570\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.621\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/AssistedTeleop.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.679\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.728\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#collision-monitor-added-watchdog-mechanism-based-on-source-timeout-parameter-with-default-blocking-behavior\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:32.987\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#removed-kinematic-limiting-in-rpp\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.027\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#how-do-dev-containers-work\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.096\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#configuring-robot-localization\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.139\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.191\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/keepout_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.292\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-pathlongeronapproach-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.422\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.473\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#replanning-at-a-constant-rate-and-if-the-path-is-invalid\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.524\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/kinematic.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.569\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#automatic-backtrace-on-crash\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.657\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#id1\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.706\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#spawning-the-robot-in-gazebo\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.747\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#send-a-goal-pose\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.949\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelControl.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:33.993\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#provided-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.104\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#change-duration-type-in-wait-action-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.147\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.199\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#collision-monitor-dynamic-radius-for-circle-type-polygons\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.254\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#behavior-tree-navigators\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.459\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.529\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#btactionserver-use-native-library-halttree\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.651\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#run-straightline-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.701\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.739\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html#description\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.822\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:34.990\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-a-launch-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.115\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/prefer_forward.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.180\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-amcl.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.237\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#expose-action-server-s-result-timeout\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.284\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/photo_at_waypoint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.327\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.583\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#nav2-controllers-and-goal-checker-plugin-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.636\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#lifecycle-node-added-bond-heartbeat-period-parameter-and-allow-disabling-the-bond-mechanism\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.689\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#simple-python-commander\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.730\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#build\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:35.857\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#costmap-2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.033\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-robot-interfaces\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.087\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.115\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/rviz-set-initial-pose.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.164\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelDriveOnHeading.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.218\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#recovery-subtree\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.258\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.355\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navigatethroughposes-and-computepaththroughposes-actions-added\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.401\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#decorator-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.562\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.607\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#selecting-the-algorithm-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.663\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/GetPoseFromPath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.773\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#computepathtopose-bt-node-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.841\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#simulating-an-odometry-system-using-gazebo\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:36.892\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.077\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.223\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#mppi-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.272\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#create-the-behavior-tree\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.322\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.364\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#for-jazzy-and-newer\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.413\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.616\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.774\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.830\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#nav2-rviz-panel-action-feedback-information\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:37.888\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.003\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#sensor-msgs-pointcloud-to-sensor-msgs-pointcloud2-change\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.176\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.218\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.263\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.319\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelCoverage.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.363\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.412\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#costmap-2d-node-default-constructor\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.503\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#feedback-for-navigation-failures\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.673\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#spin-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.725\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#ray-tracing-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.768\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#state-estimation\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.821\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html#regulated-pure-pursuit-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.919\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#simple-commander-api-allows-multi-robot-namespacing\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:38.961\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.005\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.197\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.273\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#setting-up-odometry-on-your-robot\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.390\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#savitzky-golay-smoother\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.434\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#standards\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.484\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/controls/RoundRobin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.525\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.735\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.876\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:39.931\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.019\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#controllerserver-new-parameter-failure-tolerance\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.082\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navigatetopose-action-feedback-updates\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.296\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#give-behavior-server-access-to-both-costmaps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.359\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/smac/configuring-smac-2d.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.411\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.460\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.505\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#expanded-planner-benchmark-tests\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.554\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/PlannerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.830\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputeCoveragePath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.885\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.936\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#composition\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:40.998\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#added-assisted-teleop\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.053\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#regulatedpurepursuit-controller-rpp-new-parameter-use-cancel-deceleration\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.150\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/rotate_to_goal.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.279\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#planner-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.340\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#euclidean-distance-2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.391\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelBackUp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.448\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#for-docker-based-development\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.551\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-navigator-groot-multiple-navigators\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.636\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#cost-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.809\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsStuck.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.868\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:41.979\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.066\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.109\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#visualizing-footprint-in-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.146\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html#new-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.338\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#move-error-code-enumerations\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.539\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#obstacles-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.619\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#substitution-in-parameter-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.678\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#respawn-support-in-launch-and-lifecycle-manager\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.860\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/SmootherSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:42.906\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.024\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.077\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.130\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#navigate-to-pose-with-replanning-and-recovery\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.182\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-action-nodes-exception-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.359\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/rviz_initial.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.421\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.662\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#build-run-and-verification\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.713\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#run-gradientlayer-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.902\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:43.959\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.075\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#visualization-using-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.129\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#add-velocitypolygon-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.174\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.225\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html#graceful-controller-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.270\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.496\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#for-iron-and-older\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.543\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smac-planner-start-pose-included-in-path\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.590\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#navigation-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.656\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#goal-checkers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.701\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-slam\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.809\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#rewrittenyaml-could-add-new-parameters-to-yamls\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:44.946\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-navfn.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.010\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#pass-the-plugin-name-through-the-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.053\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html#rotation-shim-controller-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.128\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.221\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.285\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#run-pure-pursuit-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.511\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#mapping-and-localization\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.566\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#add-plugin-library-name-to-config\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.669\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-collision-monitor.html#provided-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.769\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-behavior-tree-navigator-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:45.821\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#changes-to-mppi-goal-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.028\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#id2\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.088\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#gps-localization-overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.194\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#creating-a-new-behavior-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.271\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#goal-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.326\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#controllers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.516\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.661\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#odometry-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.711\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldASmootherRecoveryHelp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.770\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.809\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html#provided-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:46.921\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#nav2-deployment-image\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.053\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#new-clearcostmapexceptregion-and-clearcostmaparoundrobot-bt-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.106\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#global-frame-removed-from-2-bt-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.154\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/GoalCheckerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.198\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#trajectory-critics\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.248\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-option-for-the-voxel-and-obstacle-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.392\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-graceful-cancellation-api-for-controllers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.577\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#smac-planner-debug-param-name-change\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.629\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#new-behavior-tree-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.675\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#behavior-trees\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.719\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#nav2-launch-options\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.843\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/NavigateToPose.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:47.907\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.101\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#option-to-disable-zero-velocity-publishing-on-goal-exit\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.154\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#modify-navigation2-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.212\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#costmap-filters-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.316\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#docking-action-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.381\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.449\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_and_pause_near_goal_obstacle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.620\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html#jazzy-roadmap\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.673\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/binary_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.771\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/twirling.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.829\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.886\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#export-and-make-gradientlayer-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.923\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/navigate-to-pose.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:48.981\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.163\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#full-stack-uses-node-clocks\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.288\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.334\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html#creating-dev-containers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.427\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/GoalUpdater.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.471\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#planner-and-controller-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.675\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#change-and-fix-behavior-of-dynamic-parameter-change-detection\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.802\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.861\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/path_align.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.911\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:49.966\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GoalReached.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.017\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#environmental-representation\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.251\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#chargingdock-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.299\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#enable-the-plugin-in-costmap2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.352\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#replanning-only-if-path-is-invalid\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.401\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#modifying-your-bt-xml\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.454\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#major-improvements-to-smac-planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.504\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelAssistedTeleop.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.593\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.708\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/navstack-ready.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.753\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/index.html#id1\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.808\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#static-layer-new-parameter-footprint-clearing-enabled\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.869\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#thetastarplanner\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:50.923\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#demo-execution\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.025\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.073\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navfn-planner-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.246\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#goal-checker-api-changed\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.296\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/controls/RecoveryNode.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.400\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.443\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#docker-container-images\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.492\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-plugins/standard_traj_generator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.541\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.581\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.762\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smac-planner-path-tolerances\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.860\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#initialize-the-location-of-turtlebot-3\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.907\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#transforms-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:51.969\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#exporting-the-planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.038\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-a-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.084\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#map-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.180\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#behavior-tree-uses-error-codes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.290\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#costmap2d-current-usage\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.389\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#run-behavior-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.435\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#write-a-new-costmap2d-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.495\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#understanding-ros-docker-images\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.609\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#adding-physical-properties\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.665\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#create-a-new-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.815\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#more-stable-regulation-on-curves-for-long-lookahead-distances\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.874\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Wait.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:52.937\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#for-docker-based-deployment\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.053\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-plugins/limited_accel_generator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.108\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#introduction-of-soft-real-time-action-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.162\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#api-change-for-nav2-core\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.347\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.403\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#new-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.504\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#launch-navigation2\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.559\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#computepathtopose-action-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.617\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/DistanceController.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.679\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#behaviors\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.872\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#extending-the-btservicenode-to-process-service-results\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:53.974\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#decorator-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.028\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#smacplanner\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.105\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_with_consistent_replanning_and_if_path_becomes_invalid.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.154\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.207\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-safety-behavior-model-limit-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.448\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.500\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.543\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.601\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#plugin-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.645\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#costmap2d-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.753\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#exporting-the-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.908\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#nav2-academic-overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:54.953\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#rolling-development-source\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.004\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#exporting-the-behavior-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.049\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.160\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/smac/configuring-smac-lattice.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.208\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.262\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.441\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#added-optional-collision-checking-for-the-docking-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.496\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/FollowPath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.601\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/pose_progress_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.652\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/related_projects.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.724\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-model-predictive-path-integral-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.776\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/PathExpiringTimer.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:55.963\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.019\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#recovery-behavior-timeout\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.135\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#change-polygon-points-parameter-format-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.199\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.257\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#adding-docking-server-to-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.342\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#velocity-deadband-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.562\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-rviz-panel-for-docking\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.615\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#footprint-collision-checker-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.659\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/index.html#contact\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.722\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.770\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:56.874\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/TimeExpired.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.012\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#new-nav2-velocity-smoother\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.059\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#controller-plugin-selection\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.112\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#addition-of-new-mppi-cost-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.171\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#waypoint-task-executors\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.274\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#backup-recovery-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.336\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#important-docker-commands\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.525\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/NavigateThroughPoses.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.604\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#appendix\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.663\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.799\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#id4\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:57.882\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.071\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.201\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#preliminaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.286\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#build-run-and-verification\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.335\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.383\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.579\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smootherselector-bt-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.710\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-amcl.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.766\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/goal_align.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.888\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:58.954\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#prerequisites\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.100\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#developer-certification-of-origin-dco\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.216\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ProgressCheckerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.268\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Spin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.345\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#launch-and-build-files\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.429\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#goal-angle-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.672\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/simple_goal_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.726\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.786\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#examples-and-demos\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.840\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#run-dynamic-object-following-in-nav2-simulation\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.897\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#reduce-nodes-and-executors\u001b[0m\n", + "\u001b[32m2024-12-06 14:41:59.943\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#server-updates\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.056\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#new-particle-filter-messages\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.167\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#changes-to-mppi-path-handling-for-directionality\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.219\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#run-your-custom-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.263\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#map-server-re-work\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.323\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsBatteryLow.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.430\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#publish-costmap-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.492\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#logged-gps-waypoint-follower-waypoint-logging\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.686\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/gazebo_turtlebot1.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.740\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html#velocity-smoother-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/iterator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.846\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#backup-bt-node-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:00.970\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-node-in-nav2-collision-monitor-collision-detector\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.254\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#prepare-filter-mask\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.317\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.400\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#trajectory-visualization\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.512\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/oscillation.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.536\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/rviz-not-started.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.745\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#behavior-tree-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.807\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/input_at_waypoint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.871\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#setup-gps-localization-system\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:01.932\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#configuring-docking-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.043\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsPathValid.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.094\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-large-project\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.264\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#nav2-development-image\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.349\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#build-and-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.397\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-denoise-costmap-layer-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.523\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#urdf-and-the-robot-state-publisher\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.574\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#renamed-ros-parameter-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.631\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.774\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#install\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.875\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.930\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:02.982\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.044\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#pass-the-plugin-name-through-the-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.086\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#process\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.191\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/AreErrorCodesPresent.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.303\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#controller-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.348\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#followpoint-capability\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.423\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#launch-and-build-files\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.536\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.581\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#generate-doxygen\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.693\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.827\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.890\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#dynamic-composition\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.936\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#new-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:03.991\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#use-interpolation-rpp-parameter-depreciated\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.098\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/PathLongerOnApproach.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.155\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/simple_progress_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.360\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-truncatepathlocal-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.419\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.481\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.575\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.635\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/visualization.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.691\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.905\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#plugin-libraries-in-bt-navigator-only-includes-custom-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:04.953\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.052\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.096\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#default-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.148\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#condition-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.190\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.383\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsBatteryCharging.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.443\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#global-positioning-localization-and-slam\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.552\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-graceful-motion-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.610\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.670\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#enable-speed-filter\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.721\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-recovery\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:05.910\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/TransformAvailable.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.043\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_recovery.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.094\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#map-saver-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.151\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.211\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.263\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-navigation2\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.454\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#configuring-primary-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.595\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#removed-use-sim-time-from-yaml\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.678\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#robot-localization-demo\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.720\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html#new-packages\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:06.793\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#run-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.049\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.112\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-amcl.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.189\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#setup-and-prerequisites\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.242\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.301\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#dynamic-enabling-disabling-of-sources-polygons-in-collision-monitor-detector\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.572\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#simplified-costmap2dros-constructors\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.623\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.690\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/controls/PipelineSequence.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.745\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/inflation.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.807\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:07.923\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.027\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#opennav-docking-project\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.081\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#parameterizable-collision-checking-in-rpp\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.147\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#dock-database\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.195\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#prerequisites\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.307\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#demo-execution\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.395\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-angle-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.548\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-roundrobin\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.609\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#added-gps-waypoint-follower-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:08.654\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.270\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/navigation_with_recovery_behaviours.gif: 'utf-8' codec can't decode byte 0xf7 in position 10: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.416\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#create-a-new-navigator-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.602\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/range.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.645\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#edit-behavior-trees\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.704\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GloballyUpdatedGoal.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.840\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#twirling-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.889\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:09.934\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#static-transform-publisher-demo\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.121\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#transforms-in-navigation2\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.168\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#adding-a-custom-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.210\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.313\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#other-forms\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.373\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.463\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-align-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.683\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#behavior-server-error-codes\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.872\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#planner-controller-smoother-and-recovery-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.930\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-collision-monitor-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:10.978\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#action-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.176\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GoalUpdated.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.231\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navigatetopose-bt-node-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.278\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#docking-with-static-infrastructure-or-dynamic-docking\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.382\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.438\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelWait.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.486\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.545\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#configure-costmap-filter-info-publisher-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.708\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/follow_point.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.812\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.866\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#setup\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.924\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#obstacle-marking-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:11.980\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#removed-bt-xml-launch-configurations\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.040\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#interactive-gps-waypoint-follower\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.315\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#sensor-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.371\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#backup-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.425\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/stopped_goal_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.467\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#configuring-the-robot-s-footprint\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.568\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#progress-checkers\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.742\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html#smoother-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:42:12.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#creating-a-new-bt-plugin\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "=== Document ===\n", + "Title: Getting Started\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Installation\n", + "Jazzy introduced the new Gazebo modern simulator, replacing Gazebo Classic.\n", + "Thus, for Jazzy and newer, the installation packages and instructions are slightly different to pull in the appropriate packages.\n", + "ForJazzy and newer, install the Turtlebot 3 & 4 packages for Gazebo Modern. It should be automatically installed withnav2_bringup:\n", + "ForIron and older, install Turtlebot 3 packages for gazebo classic:\n", + "\n", + "## Running the Example\n", + "\n", + "\n", + "## Navigating\n", + "After starting, the robot initially has no idea where it is. By default,\n", + "Nav2 waits for you to give it an approximate starting position. Take a look\n", + "at where the robot is in the Gazebo world, and find that spot on the map. Set\n", + "the initial pose by clicking the “2D Pose Estimate” button in RViz, and then\n", + "down clicking on the map in that location. You set the orientation by dragging\n", + "forward from the down click.\n", + "If you are using the defaults so far, the robot should look roughly like this.\n", + "If you don’t get the location exactly right, that’s fine. Nav2 will refine\n", + "the position as it navigates. You can also, click the “2D Pose\n", + "Estimate” button and try again, if you prefer.\n", + "Once you’ve set the initial pose, the transform tree will be complete and\n", + "Nav2 will be fully active and ready to go. You should see the robot and particle\n", + "cloud now.\n", + "Next, click the “Navigaton2 Goal” button and choose a destination.\n", + "This will call the BT navigator to go to that goal through an action server.\n", + "You can pause (cancel) or reset the action through the Nav2 rviz plugin shown.\n", + "Now watch the robot go!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'Install the Nav2 packages using your operating system’s package '\n", + " 'manager:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--nav2-minimal-tb*\\n',\n", + " 'context': 'ForJazzy and newer, install the Turtlebot 3 & 4 packages for '\n", + " 'Gazebo Modern. It should be automatically installed '\n", + " 'withnav2_bringup:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--turtlebot3-gazebo\\n',\n", + " 'context': 'ForIron and older, install Turtlebot 3 packages for gazebo '\n", + " 'classic:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " '\\n'\n", + " 'export\\n'\n", + " 'TURTLEBOT3_MODEL\\n'\n", + " '=\\n'\n", + " 'waffle\\n'\n", + " '# Iron and older only with Gazebo Classic\\n'\n", + " 'export\\n'\n", + " 'GAZEBO_MODEL_PATH\\n'\n", + " '=\\n'\n", + " '$GAZEBO_MODEL_PATH\\n'\n", + " ':/opt/ros//share/turtlebot3_gazebo/models\\n'\n", + " '# Iron and older only with Gazebo Classic',\n", + " 'context': 'Set key environment variables, some of which are only required '\n", + " 'for Iron and older:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'In the same terminal, run:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Planner Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When theplanner_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_navfn_planner::NavfnPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': '“nav2_navfn_planner::NavfnPlanner”',\n", + " 'filename': 'planner_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Nav2 Behavior Trees\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Averybasic, but functional, navigator can be seen below.',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Tree XML Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Plugins\n", + "\n", + "\n", + "## Condition Plugins\n", + "\n", + "\n", + "## Control Plugins\n", + "\n", + "\n", + "## Decorator Plugins\n", + "\n", + "\n", + "## Example\n", + "This Behavior Tree replans the global path periodically at 1 Hz and it also has\n", + "recovery actions.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This Behavior Tree replans the global path periodically at 1 Hz '\n", + " 'and it also has\\n'\n", + " 'recovery actions.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: RemovePassedGoals\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'A vector of goals with goals removed in proximity to the robot',\n", + " 'filename': 'ComputePathThroughPoses',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dashing to Eloquent\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Packages\n", + "Navigation2 now includes a new packagenav2_waypoint_follower.\n", + "The waypoint follower is an action server that will take in a list of waypoints to follow and follow them in order.\n", + "There is a parameterstop_on_failurewhether the robot should continue to the next waypoint on a single waypoint failure,\n", + "or to return fail to the action client.\n", + "The waypoint follower is also a reference application for how to use the Navigation2 action server to complete a basic autonomy task.\n", + "Navigation2 now supports new algorithms for control and SLAM.\n", + "The Timed-Elastic Band (TEB) controller was implementedand can be found here.\n", + "It is its own controller plugin that can be used instead of the DWB controller.\n", + "Nav2 also supports SLAM Toolbox as the default SLAM implementation for ROS 2.\n", + "This replaces the use of Cartographer.\n", + "\n", + "## New Plugins\n", + "Eloquent introduces back in pluginlib plugins to the navigation stack.nav2_coredefines the plugin header interfaces to be used to implement controller, planner, recovery, and goal checker plugins.\n", + "All algorithms (NavFn, DWB, recoveries) were added as plugin interfaces and the general packages for servers were created.nav2_planneris the action server for planning that hosts a plugin for the planner.nav2_controlleris the action server for controller that hosts a plugin for the controller.nav2_recoveryis the action server for recovery that hosts a plugin for recovery.\n", + "New recovery plugins were added including backup, which will take in a distance to back up, if collision-free.\n", + "Additionally, the wait recovery was added that will wait a configurable period of time before trying to navigate again.\n", + "This plugin is especially helpful for time-dependent obstacles or pausing navigation for a scene to become less dynamic.\n", + "Many new behavior tree nodes were added. These behavior tree nodes are hard-coded in the behavior tree engine.\n", + "Behavior tree cpp v3 supports plugins and will be converted in the next release.\n", + "\n", + "## Navigation2 Architectural Changes\n", + "Thenav2_world_modelpackage was removed. The individualnav2_plannerandnav2_controllerservers now host their relevant costmaps.\n", + "This was done to reduce network traffic and ensure up-to-date information for the safety-critical elements of the system.\n", + "As above mentions, plugins were introduced into the stack and these servers each host plugins for navigation, control, and costmap layers.\n", + "Map server was substantially refactored but the external API remains the same. It now uses the SDL library for image loading.\n", + "TF-based positioning is now used for pose-estimation everywhere in the stack.\n", + "Prior, some elements of the navigation stack only updated its pose from the/amcl_posetopic publishing at an irregular rate.\n", + "This is obviously low-accuracy and high-latency.\n", + "All positioning is now based on the TF tree from the global frame to the robot frame.\n", + "Prior to Eloquent, there were no ROS 2 action servers and clients available.\n", + "Navigation2, rather, used an interface we called Tasks.\n", + "Eloquent now contains actions and a simple action server interface was created and is used now throughout the stack.\n", + "Tasks were removed.\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PathDistCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": PathDistCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Plugin Tutorials\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Robots Using\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: NavFn Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'use_astar\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'allow_unknown\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'If true, the last pose of the path generated by the planner will '\n", + " 'have its orientation set to the approach orientation, i.e. the '\n", + " 'orientation of the vector connecting the last two points of the '\n", + " 'path',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Simple Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'max_its\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " 'w_data\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '0.3',\n", + " 'context': 'Weight to apply to smooth the path (smooths it)',\n", + " 'filename': '>=1',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ComputePathThroughPoses\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Compute path through poses error code. '\n", + " 'SeeComputePathThroughPosesaction message for the enumerated set '\n", + " 'of error codes.',\n", + " 'filename': 'ComputePathThroughPoses',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Tree XML Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Plugins\n", + "\n", + "\n", + "## Condition Plugins\n", + "\n", + "\n", + "## Control Plugins\n", + "\n", + "\n", + "## Decorator Plugins\n", + "\n", + "\n", + "## Example\n", + "This Behavior Tree replans the global path periodically at 1 Hz and it also has\n", + "recovery actions.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This Behavior Tree replans the global path periodically at 1 Hz '\n", + " 'and it also has\\n'\n", + " 'recovery actions.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Container Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Creating Dev Containers\n", + "Before creating a dev container, you’ll want to choose the exact configuration to use. By default the.devcontainer/devcontainer.jsonconfiguration is selected, however you can also choose any otherdevcontainer.jsonfile in the.devcontainer/directory, where such configurations can be nested to provide greater customization: either by targeting different stages within different Dockerfiles, overriding any merged metadata or default properties, or inclusion of additional extensions and alternate commands.\n", + "\n", + "## Building the image\n", + "When first creating Dev Containers, any supporting tool or service used will download and build the docker images needed to run the container. This includes pulling any parent images the project’s Dockerfile buildsFROM, as well as any tags or layers declared viacacheFrom, as specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until such layers are updated and pushed to the image registry.\n", + "Specifically, for this project, the defaultdevcontainer.jsonfile targets thedeverstage within the project’s root Dockerfile, the stage that also includes handy tools for developing the project, such as bash auto completion. This stage is in turn builtFROMthebuilderstage, the stage that only includes the dependencies needed for building the project, as reused by the project’s CI. For example, thedeverstage modifies/etc/bash.bashrcto automatically sourceinstall/setup.bashfrom the underlay workspace, ensuring all VS Code extensions are loaded with the correct environment, while avoiding any race conditions during installation and startup.\n", + "To speed up the initial build, images layers from thisbuilderstage are cached by pulling the same image tag used by the project’s CI, hosted from the image registry. This ensures your local dev container replicates our CI environment as close as possible, while benefiting from any cached work preemptively performed by the CI. Yet, this still allows you to customize the project’s Dockerfile and rebuild the container, without needing to update CI images to reflect your local modifications.\n", + "Once the base image from the target stage is built, the supporting tool or service may then add additional layers to the image, such as installing additionalfeaturesor customizations. For VS Code, this also includes some fancy file caching for any extensions to install later. Once this custom image is built, it is then used to start the dev container.\n", + "\n", + "## Starting the container\n", + "When first creating Dev Containers, any supporting tool or service will invoke a sequence of commands specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until the container is rebuilt, triggered by either updating the Dockerfile, base image, or.devcontainer/config.\n", + "Specifically, for this project, the defaultdevcontainer.jsonconfig executes theonCreateCommandto initially colcon cache, clean, and build the overlay workspace for the project. This ensures the workspace is precompiled and ready to use, while also ensuring any changes to the project’s source code are reflected in the container. This is useful for:\n", + "While the colcon workspace is being built, VS Code will simultaneously install any specified extensions and settings. Next theupdateContentCommandis executed, which reruns whenever the container is started or restarted. Specifically, for this project, this command re-cleans and re-builds the same colcon workspace as before, but only for invalidated packages detected by colcon cache using the lockfiles initialized during theonCreateCommand. This caching behavior also replicates the project’s CI workflow. This is useful for:\n", + "Finally, thepostCreateCommandis executed, which also reruns whenever the container is started or restarted. Specifically, for this project, this command makes a last few tweaks to the user’s environment to improve the development experience.\n", + "To speed up subsequent startups, volumes that are mounted to the container store a persistent ccache and colcon workspace, while the environment is set to enableccacheviacolcon mixins. These volumes are labeled using thedevcontainerIdvariable, which uniquely identify the dev container on a Docker host, allowing us to refer to a common identifier that is unique to the dev container, while remaining stable across rebuilds. This is useful for:\n", + "Additionally, the container can be grantedprivilegedand non-defaultLinux capabilities, connected using thehostnetwork mode andIPCandPIDspaces, with a relaxedsecurity configurationand seccomp confinement for native debugging and external connectivity. This is useful for:\n", + "\n", + "## Using Dev Containers\n", + "Once the dev container has been created and setup completed, VS Code will open a new workspace directly from the project’s root directory, which itself is mounted within the source directory in the overlay colcon workspace. From here you can build, test, and debug the project as you normally would, with the added benefit of having the project’s dependencies, intellisense, linters, and other extensions pre-configured and ready to use. Simply open a new terminal (Crtl+Shift+`), cd to the root of the colcon workspace, and run the usual colcon commands.\n", + "\n", + "## Terminals\n", + "If you prefer using an alternate terminal emulator, rather than the built-in VS Code terminal, you can open a separate shell session by simply using the Dev Container CLI or directly using the Docker CLI via theexecsubcommands.\n", + "\n", + "## Lifecycle\n", + "While using the dev container, try and keep in mind the lifecycle of the container itself. Specifically, containers are ephemeral, meaning they are normally destroyed and recreated whenever the dev environment is rebuilt or updated. Subsequently, a best practice is to avoid storing any persistent data within the container, and instead utilize the project’s source directory, or a separate mounted volume. When altering the development environment inside the container, try to remember to codify your changes into the Dockerfile, or thedevcontainer.jsonconfig file, so that they can be easily reproduced and shared with others.\n", + "\n", + "## Rebuilding\n", + "From time to time, you may need to rebuild the dev container, either because the base image, or.devcontainer/config was updated, or simply out of wanting a new fresh development environment. To do so, simply open the Command Palette (Ctrl+Shift+P) and select theRemote-Containers:RebuildContainercommand.\n", + "For example, you may need to rebuild the dev container when:\n", + "When necessary, you can also rebuild the container from scratch, e.i. without caching from docker, by selecting theRemote-Containers:RebuildContainerWithoutCachecommand. This instead omits the--cache-fromflag from thedockerbuildxcommand, while also adding the--no-cacheand--pullflags to prevent caching from any existing image layers, using only the latest images from a container registry.\n", + "Rebuilding without caching may be necessary when:\n", + "Specifically, for this project, volumes remain unaffected by this rebuilding process: i.e. those used to mount the ccache directory or colcon workspace. While volume management is left to the user’s discretion, other projects may of course handle this differently, so be sure to check the./devcontainerconfiguration to inspect how various container resources may be managed.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'find\\n'\n", + " '/tmp\\n'\n", + " '-type\\n'\n", + " 'f\\n'\n", + " '-path\\n'\n", + " '\"*/devcontainers-*/env-loginInteractiveShell.json\"\\n'\n", + " '-exec\\n'\n", + " '\\\\\\n'\n", + " 'jq\\n'\n", + " '-r\\n'\n", + " '\\'to_entries | .[] | \"\\\\(.key)=\\\\(.value | @sh)\"\\'\\n'\n", + " '{}\\n'\n", + " '\\\\;\\n'\n", + " '>\\n'\n", + " '.env\\n'\n", + " '\\n'\n", + " 'source\\n'\n", + " '.env\\n',\n", + " 'context': 'The environment provided byuserEnvProbecan be sourced manually. '\n", + " 'E.g. for the defaultloginInteractiveShellprobe:',\n", + " 'filename': 'loginInteractiveShell',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Regulated Pure Pursuit\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Regulated Pure Pursuit Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController\"\\n'\n", + " 'desired_linear_vel\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'min_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'max_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'lookahead_time\\n'\n", + " ':\\n'\n", + " '1.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_velocity_scaled_lookahead_dist\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'min_approach_linear_velocity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'approach_velocity_scaling_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'use_collision_detection\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_allowed_time_to_collision_up_to_carrot\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'use_regulated_linear_velocity_scaling\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_fixed_curvature_lookahead\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'curvature_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'use_cost_regulated_linear_velocity_scaling\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'regulated_linear_scaling_min_radius\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'regulated_linear_scaling_min_speed\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'use_rotate_to_heading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'allow_reversing\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotate_to_heading_min_angle\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'max_robot_pose_search_dist\\n'\n", + " ':\\n'\n", + " '10.0',\n", + " 'context': 'Note: Needsuse_fixed_curvature_lookaheadto betrue',\n", + " 'filename': 'true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Planner and Controller Servers\n", + "Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice.\n", + "The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment.\n", + "The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station.\n", + "As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server.\n", + "\n", + "## Selecting the Algorithm Plugins\n", + "In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server.\n", + "\n", + "## Planner Server\n", + "The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility.\n", + "As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments.\n", + "One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots.\n", + "Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds.\n", + "There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration.\n", + "\n", + "## Summary\n", + "\n", + "\n", + "## Example Configuration\n", + "An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Controller Server\n", + "The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity.\n", + "TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint.\n", + "Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots.\n", + "Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots.\n", + "The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots.\n", + "\n", + "## Summary\n", + "All of these algorithms work for both circular and non-circular robots.\n", + "\n", + "## Example Configuration\n", + "Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Non-circular Differential, Non-circular Omnidirectional',\n", + " 'filename': 'SmacLatticeplanner',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'All of these algorithms work for both circular and non-circular '\n", + " 'robots.',\n", + " 'filename': 'TrajectoryGenerationplugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Collision Detector Node\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Features\n", + "Similarly to the Collision Monitor, the Collision Detector uses robot’s relative polygons to define “zones”.\n", + "However, unlike the Collision Monitor that uses different behavior models, the Collision Detector does not use any of them and therefore theaction_typeshould always be set tonone. If set to anything else, it will throw an error\n", + "The zones around the robot and the data sources are the same as for the Collision Monitor, with the exception of the footprint polygon, which is not supported by the Collision Detector.\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Polygons parameters\n", + "is the corresponding polygon name ID selected for this type.\n", + "\n", + "## Observation sources parameters\n", + "is the corresponding data source name ID selected for this type.\n", + "\n", + "## Example\n", + "Here is an example of configuration YAML for the Collision Detector.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'collision_detector\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'base_shift_correction\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonFront\"\\n'\n", + " ']\\n'\n", + " 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"pointcloud\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"/intel_realsense_r200_depth/points\"\\n'\n", + " 'min_height\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_height\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'Here is an example of configuration YAML for the Collision '\n", + " 'Detector.',\n", + " 'filename': 'source_timeout:0.0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Costmap 2D\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Costmap2D ROS Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thepluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Plugin Parameters\n", + "\n", + "\n", + "## Costmap Filters Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ',\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'footprint_padding\\n'\n", + " ':\\n'\n", + " '0.03\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '# radius set and used, so no footprint points\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " '# no frame set, uses frame from message\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"PointCloud2\"\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'subscribe_to_updates\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'inflate_unknown\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'inflate_around_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': '“nav2_costmap_2d::InflationLayer”',\n", + " 'filename': 'plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Map Server / Saver\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Map Saver Parameters\n", + "\n", + "\n", + "## Map Server Parameters\n", + "\n", + "\n", + "## Costmap Filter Info Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'map_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"turtlebot3_world.yaml\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'map_saver\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'save_map_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'free_thresh_default\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'occupied_thresh_default\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'filter_space_value=base+multiplier*mask_value',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Roadmaps\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Jazzy Roadmap\n", + "\n", + "\n", + "## Iron Roadmap\n", + "\n", + "\n", + "## Humble Roadmap\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Simple Commander API\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage.\n", + "A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults).\n", + "You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints().\n", + "\n", + "## Commander API\n", + "The methods provided by the basic navigator are shown below, with inputs and expected returns.\n", + "If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype.\n", + "New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches.\n", + "\n", + "## Costmap API\n", + "This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API.\n", + "\n", + "## Footprint Collision Checker API\n", + "This is a Python3 API for a Footprint Collision Checker.\n", + "It provides the needed methods to manipulate the coordinates\n", + "and calculate the cost of a Footprint in a given map.\n", + "\n", + "## Examples and Demos\n", + "All of these can be found in thepackage.\n", + "Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user:\n", + "Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'from\\n'\n", + " 'nav2_simple_commander.robot_navigator\\n'\n", + " 'import\\n'\n", + " 'BasicNavigator\\n'\n", + " 'import\\n'\n", + " 'rclpy\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'nav\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ')\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# if autostarted, else use lifecycleStartup()\\n'\n", + " '# ...\\n'\n", + " 'path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getPath\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ',\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'smoothed_path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'smoothPath\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_duration\\n'\n", + " '>\\n'\n", + " '600\\n'\n", + " ':\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'cancelTask\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'You may use this simple commander preempt commands of the same '\n", + " 'type (e.g. you can preempt agoToPose()with anothergoToPose()) '\n", + " 'but you must explicitly cancel a current command and issue a new '\n", + " 'one if switching betweengoToPose(),goThroughPoses(), '\n", + " 'orfollowWaypoints().',\n", + " 'filename': 'followWaypoints()',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Setting Up the Robot’s Footprint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Footprint Introduction\n", + "The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans.\n", + "The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used.\n", + "For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization.\n", + "For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot.\n", + "Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Configuring the Robot’s Footprint\n", + "In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps.\n", + "Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot.\n", + "Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot.\n", + "For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We will now confirm that we have properly set upsam_bot’s footprint.\n", + "First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below.\n", + "After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor.\n", + "Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below.\n", + "Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors.\n", + "Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following:\n", + "We should now be able to visualize the footprints in RViz, which will be discussed in the next section.\n", + "\n", + "## Visualizing Footprint in RViz\n", + "To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot:\n", + "On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot:\n", + "\n", + "## Conclusion\n", + "In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function.\n", + "As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '188\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '189\\n'\n", + " 'footprint\\n'\n", + " ':\\n'\n", + " '\"[\\n'\n", + " '[0.21,\\n'\n", + " '0.195],\\n'\n", + " '[0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '0.195]\\n'\n", + " ']\"\\n'\n", + " '190\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Below is the code snippet fromnav2_params.yamldefining the local '\n", + " 'costmap footprint. In this configuration file, '\n", + " 'thefootprintparameter of the local costmap has already been set '\n", + " 'with a rectangular-shaped footprint. This box is centered at '\n", + " 'thebase_linkframe ofsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '232\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '233\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " '234\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': 'For the global costmap, we have already set '\n", + " 'therobot_radiusparameter to create a circular footprint that '\n", + " 'matchessam_bot’s size and centered atbase_link. The parameter '\n", + " 'that was modified is shown in the code snippet below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'First, we launchlaunch/display.launch.pyto launch the robot '\n", + " 'state publisher, spawnsam_botin Gazebo, and visualizesam_botand '\n", + " 'its footprint in Rviz. The robot state publisher publishes '\n", + " 'thebase_link=>sensorstransforms defined insam_bot’s URDF, while '\n", + " 'Gazebo’s differential drive plugin publishes '\n", + " 'theodom=>base_linktransform. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'map\\n'\n", + " 'odom\\n',\n", + " 'context': 'Next, we will publish themap=>odomtransform using '\n", + " 'thestatic_transform_publisher. We publish themap=>odomtransform '\n", + " 'as static in this guide as a simple way to publish the transform '\n", + " 'and visualize the footprint. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'navigation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '\\n',\n", + " 'context': 'Lastly, we will launch Nav2 using '\n", + " 'thenav2_params.yamlconfiguration file we just made '\n", + " 'andnavigation_launch.py, the built-in launch file '\n", + " 'ofnav2_bringup. Open a new terminal and execute the following:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use.\n", + "Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package.\n", + "\n", + "## What is the Rotation Shim Controller?\n", + "This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers.\n", + "Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so.\n", + "Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task.\n", + "TheRotationShimControlleris most suitable for:\n", + "\n", + "## Configuring Rotation Shim Controller\n", + "This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through.\n", + "As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel.\n", + "The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted.\n", + "\n", + "## Configuring Primary Controller\n", + "There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity).\n", + "An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform.\n", + "\n", + "## Demo Execution\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'As such, its configuration looks very similar to that of any '\n", + " 'other plugin. In the code block below, you can see that we’ve '\n", + " 'added theRotationShimControlleras the plugin for path tracking '\n", + " 'in the controller server. You can see that we’ve also configured '\n", + " 'it below with its internal '\n", + " 'parameters,angular_dist_thresholdthroughmax_angular_accel.',\n", + " 'filename': 'max_angular_accel',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# DWB parameters\\n'\n", + " '...\\n'\n", + " '...\\n'\n", + " '...',\n", + " 'context': 'There is one more remaining parameter of '\n", + " 'theRotationShimControllernot mentioned above, '\n", + " 'theprimary_controller. This is the type of controller that your '\n", + " 'application would like to use as the primary modus operandi. It '\n", + " 'will share the same name and yaml namespace as the shim plugin. '\n", + " 'You can observe this below with the primary controller set '\n", + " 'theDWB(with the progress and goal checkers removed for brevity).',\n", + " 'filename': 'DWB',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Collision Monitor Node\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Features\n", + "The Collision Monitor uses polygons relative the robot’s base frame origin to define “zones”.\n", + "Data that fall into these zones trigger an operation depending on the model being used.\n", + "A given instance of the Collision Monitor can have many zones with different models at the same time.\n", + "When multiple zones trigger at once, the most aggressive one is used (e.g. stop > slow 50% > slow 10%).\n", + "The following models of safety behaviors are employed by Collision Monitor:\n", + "The zones around the robot can take the following shapes:\n", + "All shapes (Polygon,CircleandVelocityPolygon) are derived from basePolygonclass, so without loss of generality they would be called as “polygons”.\n", + "Subscribed footprint is also having the same properties as other polygons, but it is being obtained a footprint topic for the Approach Model.\n", + "The data may be obtained from different data sources:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Polygons parameters\n", + "is the corresponding polygon name ID selected for this type.\n", + "\n", + "## VelocityPolygon parameters\n", + "All previous Polygon parameters apply, in addition to the following unique parameters for VelocityPolygon.\n", + "\n", + "## Observation sources parameters\n", + "is the corresponding data source name ID selected for this type.\n", + "\n", + "## Example\n", + "Here is an example illustrating the common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "Here is an example of configuration YAML for the Collision Monitor.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'state_topic\\n'\n", + " ':\\n'\n", + " '\"collision_monitor_state\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'base_shift_correction\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older\\n'\n", + " 'use_realtime_priority\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ',\\n'\n", + " '\"FootprintApproach\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"circle\"\\n'\n", + " 'radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[1.0,\\n'\n", + " '1.0],\\n'\n", + " '[1.0,\\n'\n", + " '-1.0],\\n'\n", + " '[-0.5,\\n'\n", + " '-1.0],\\n'\n", + " '[-0.5,\\n'\n", + " '1.0]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'PolygonLimit\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.5,\\n'\n", + " '0.5],\\n'\n", + " '[0.5,\\n'\n", + " '-0.5],\\n'\n", + " '[-0.5,\\n'\n", + " '-0.5],\\n'\n", + " '[-0.5,\\n'\n", + " '0.5]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"limit\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'linear_limit\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'angular_limit\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_limit\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FootprintApproach\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"approach\"\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " '\"/local_costmap/published_footprint\"\\n'\n", + " 'time_before_collision\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'simulation_time_step\\n'\n", + " ':\\n'\n", + " '0.02\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " '# max_points: 5 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ',\\n'\n", + " '\"pointcloud\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"/scan\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"pointcloud\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"/intel_realsense_r200_depth/points\"\\n'\n", + " 'min_height\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_height\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'Here is an example of configuration YAML for the Collision '\n", + " 'Monitor.',\n", + " 'filename': 'source_timeout:0.0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Controller Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugins\n", + "When theprogress_checker_plugins,goal_checker_pluginorcontroller_pluginsparameters are not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'failure_tolerance\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " '# goal_checker_plugin: \"goal_checker\" For Galactic and older\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': '“dwb_core::DWBLocalPlanner”',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Velocity Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Velocity Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'velocity_smoother\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'smoothing_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'scale_velocities\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'feedback\\n'\n", + " ':\\n'\n", + " '\"OPEN_LOOP\"\\n'\n", + " 'max_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '2.5\\n'\n", + " ']\\n'\n", + " 'min_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '-0.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '-2.5\\n'\n", + " ']\\n'\n", + " 'deadband_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'velocity_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'max_accel\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '2.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '3.2\\n'\n", + " ']\\n'\n", + " 'max_decel\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '-2.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '-3.2\\n'\n", + " ']\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'odom_duration\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_realtime_priority\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'false',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Detailed Behavior Tree Walkthrough\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document serves as a reference guide to the main behavior tree (BT) used in Nav2.\n", + "There are many example behavior trees provided innav2_bt_navigator/behavior_trees,\n", + "but these sometimes have to be re-configured based on the application of the robot.\n", + "The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail.\n", + "\n", + "## Prerequisites\n", + "\n", + "\n", + "## Navigate To Pose With Replanning and Recovery\n", + "The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml.\n", + "This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions.\n", + "BTs are primarily defined in XML. The tree shown above is represented in XML as follows.\n", + "This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time.\n", + "These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree.\n", + "This can be represented in the following way:\n", + "TheNavigationsubtree mainly involves actual navigation behavior:\n", + "TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally.\n", + "The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail\n", + "(path calculation or path following), contextual recoveries will be attempted.\n", + "If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE.\n", + "The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures.\n", + "This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6).\n", + "\n", + "## Navigation Subtree\n", + "Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree.\n", + "The XML of this subtree is as follows:\n", + "This subtree has two primary actionsComputePathToPoseandFollowPath.\n", + "If either of these two actions fail, they will attempt to clear the failure contextually.\n", + "The crux of the tree can be represented with only one parent and two children nodes like this:\n", + "The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked.\n", + "While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around.\n", + "Both theComputePathToPoseand theFollowPathfollow the same general structure.\n", + "The below is theComputePathToPosesubtree:\n", + "The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree.\n", + "The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap.\n", + "Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries.\n", + "The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below:\n", + "\n", + "## Recovery Subtree\n", + "TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree.\n", + "In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient).\n", + "And the XML snippet:\n", + "The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received.\n", + "If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries.\n", + "This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”.\n", + "These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree\n", + "in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge).\n", + "If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are:\n", + "UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree.\n", + "If this renavigation was not successful, the next child of theRoundRobinwill be ticked.\n", + "For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE:\n", + "(for the sake of this example, let’s assume that the goal is never updated).\n", + "If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure).\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'BTs are primarily defined in XML. The tree shown above is '\n", + " 'represented in XML as follows.',\n", + " 'filename': 'navigate_to_pose_w_replanning_and_recovery.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'This happens until thenumber_of_retriesfor the '\n", + " 'parentRecoveryNodeis exceeded (which by default is 6).',\n", + " 'filename': 'RecoveryNode',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The XML of this subtree is as follows:',\n", + " 'filename': 'Recovery',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'And the XML snippet:',\n", + " 'filename': 'Navigation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Controller Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugins\n", + "When theprogress_checker_plugins,goal_checker_pluginorcontroller_pluginsparameters are not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'failure_tolerance\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " '# goal_checker_plugin: \"goal_checker\" For Galactic and older\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': '“dwb_core::DWBLocalPlanner”',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Denoise Layer Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"denoise_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '...\\n'\n", + " 'denoise_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'minimal_group_size\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'group_connectivity_type\\n'\n", + " ':\\n'\n", + " '8',\n", + " 'context': 'Obstacles connectivity type (is the way in which obstacles '\n", + " 'relate to their neighbors).\\n'\n", + " 'Must be 4 or 8.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: ObstacleFootprintCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": ObstacleFootprintCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up the Robot’s Footprint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Footprint Introduction\n", + "The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans.\n", + "The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used.\n", + "For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization.\n", + "For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot.\n", + "Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Configuring the Robot’s Footprint\n", + "In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps.\n", + "Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot.\n", + "Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot.\n", + "For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We will now confirm that we have properly set upsam_bot’s footprint.\n", + "First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below.\n", + "After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor.\n", + "Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below.\n", + "Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors.\n", + "Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following:\n", + "We should now be able to visualize the footprints in RViz, which will be discussed in the next section.\n", + "\n", + "## Visualizing Footprint in RViz\n", + "To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot:\n", + "On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot:\n", + "\n", + "## Conclusion\n", + "In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function.\n", + "As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '188\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '189\\n'\n", + " 'footprint\\n'\n", + " ':\\n'\n", + " '\"[\\n'\n", + " '[0.21,\\n'\n", + " '0.195],\\n'\n", + " '[0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '0.195]\\n'\n", + " ']\"\\n'\n", + " '190\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Below is the code snippet fromnav2_params.yamldefining the local '\n", + " 'costmap footprint. In this configuration file, '\n", + " 'thefootprintparameter of the local costmap has already been set '\n", + " 'with a rectangular-shaped footprint. This box is centered at '\n", + " 'thebase_linkframe ofsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '232\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '233\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " '234\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': 'For the global costmap, we have already set '\n", + " 'therobot_radiusparameter to create a circular footprint that '\n", + " 'matchessam_bot’s size and centered atbase_link. The parameter '\n", + " 'that was modified is shown in the code snippet below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'First, we launchlaunch/display.launch.pyto launch the robot '\n", + " 'state publisher, spawnsam_botin Gazebo, and visualizesam_botand '\n", + " 'its footprint in Rviz. The robot state publisher publishes '\n", + " 'thebase_link=>sensorstransforms defined insam_bot’s URDF, while '\n", + " 'Gazebo’s differential drive plugin publishes '\n", + " 'theodom=>base_linktransform. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'map\\n'\n", + " 'odom\\n',\n", + " 'context': 'Next, we will publish themap=>odomtransform using '\n", + " 'thestatic_transform_publisher. We publish themap=>odomtransform '\n", + " 'as static in this guide as a simple way to publish the transform '\n", + " 'and visualize the footprint. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'navigation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '\\n',\n", + " 'context': 'Lastly, we will launch Nav2 using '\n", + " 'thenav2_params.yamlconfiguration file we just made '\n", + " 'andnavigation_launch.py, the built-in launch file '\n", + " 'ofnav2_bringup. Open a new terminal and execute the following:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Planner Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When theplanner_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_navfn_planner::NavfnPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': '“nav2_navfn_planner::NavfnPlanner”',\n", + " 'filename': 'planner_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Voxel Layer Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Dev Container Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Creating Dev Containers\n", + "Before creating a dev container, you’ll want to choose the exact configuration to use. By default the.devcontainer/devcontainer.jsonconfiguration is selected, however you can also choose any otherdevcontainer.jsonfile in the.devcontainer/directory, where such configurations can be nested to provide greater customization: either by targeting different stages within different Dockerfiles, overriding any merged metadata or default properties, or inclusion of additional extensions and alternate commands.\n", + "\n", + "## Building the image\n", + "When first creating Dev Containers, any supporting tool or service used will download and build the docker images needed to run the container. This includes pulling any parent images the project’s Dockerfile buildsFROM, as well as any tags or layers declared viacacheFrom, as specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until such layers are updated and pushed to the image registry.\n", + "Specifically, for this project, the defaultdevcontainer.jsonfile targets thedeverstage within the project’s root Dockerfile, the stage that also includes handy tools for developing the project, such as bash auto completion. This stage is in turn builtFROMthebuilderstage, the stage that only includes the dependencies needed for building the project, as reused by the project’s CI. For example, thedeverstage modifies/etc/bash.bashrcto automatically sourceinstall/setup.bashfrom the underlay workspace, ensuring all VS Code extensions are loaded with the correct environment, while avoiding any race conditions during installation and startup.\n", + "To speed up the initial build, images layers from thisbuilderstage are cached by pulling the same image tag used by the project’s CI, hosted from the image registry. This ensures your local dev container replicates our CI environment as close as possible, while benefiting from any cached work preemptively performed by the CI. Yet, this still allows you to customize the project’s Dockerfile and rebuild the container, without needing to update CI images to reflect your local modifications.\n", + "Once the base image from the target stage is built, the supporting tool or service may then add additional layers to the image, such as installing additionalfeaturesor customizations. For VS Code, this also includes some fancy file caching for any extensions to install later. Once this custom image is built, it is then used to start the dev container.\n", + "\n", + "## Starting the container\n", + "When first creating Dev Containers, any supporting tool or service will invoke a sequence of commands specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until the container is rebuilt, triggered by either updating the Dockerfile, base image, or.devcontainer/config.\n", + "Specifically, for this project, the defaultdevcontainer.jsonconfig executes theonCreateCommandto initially colcon cache, clean, and build the overlay workspace for the project. This ensures the workspace is precompiled and ready to use, while also ensuring any changes to the project’s source code are reflected in the container. This is useful for:\n", + "While the colcon workspace is being built, VS Code will simultaneously install any specified extensions and settings. Next theupdateContentCommandis executed, which reruns whenever the container is started or restarted. Specifically, for this project, this command re-cleans and re-builds the same colcon workspace as before, but only for invalidated packages detected by colcon cache using the lockfiles initialized during theonCreateCommand. This caching behavior also replicates the project’s CI workflow. This is useful for:\n", + "Finally, thepostCreateCommandis executed, which also reruns whenever the container is started or restarted. Specifically, for this project, this command makes a last few tweaks to the user’s environment to improve the development experience.\n", + "To speed up subsequent startups, volumes that are mounted to the container store a persistent ccache and colcon workspace, while the environment is set to enableccacheviacolcon mixins. These volumes are labeled using thedevcontainerIdvariable, which uniquely identify the dev container on a Docker host, allowing us to refer to a common identifier that is unique to the dev container, while remaining stable across rebuilds. This is useful for:\n", + "Additionally, the container can be grantedprivilegedand non-defaultLinux capabilities, connected using thehostnetwork mode andIPCandPIDspaces, with a relaxedsecurity configurationand seccomp confinement for native debugging and external connectivity. This is useful for:\n", + "\n", + "## Using Dev Containers\n", + "Once the dev container has been created and setup completed, VS Code will open a new workspace directly from the project’s root directory, which itself is mounted within the source directory in the overlay colcon workspace. From here you can build, test, and debug the project as you normally would, with the added benefit of having the project’s dependencies, intellisense, linters, and other extensions pre-configured and ready to use. Simply open a new terminal (Crtl+Shift+`), cd to the root of the colcon workspace, and run the usual colcon commands.\n", + "\n", + "## Terminals\n", + "If you prefer using an alternate terminal emulator, rather than the built-in VS Code terminal, you can open a separate shell session by simply using the Dev Container CLI or directly using the Docker CLI via theexecsubcommands.\n", + "\n", + "## Lifecycle\n", + "While using the dev container, try and keep in mind the lifecycle of the container itself. Specifically, containers are ephemeral, meaning they are normally destroyed and recreated whenever the dev environment is rebuilt or updated. Subsequently, a best practice is to avoid storing any persistent data within the container, and instead utilize the project’s source directory, or a separate mounted volume. When altering the development environment inside the container, try to remember to codify your changes into the Dockerfile, or thedevcontainer.jsonconfig file, so that they can be easily reproduced and shared with others.\n", + "\n", + "## Rebuilding\n", + "From time to time, you may need to rebuild the dev container, either because the base image, or.devcontainer/config was updated, or simply out of wanting a new fresh development environment. To do so, simply open the Command Palette (Ctrl+Shift+P) and select theRemote-Containers:RebuildContainercommand.\n", + "For example, you may need to rebuild the dev container when:\n", + "When necessary, you can also rebuild the container from scratch, e.i. without caching from docker, by selecting theRemote-Containers:RebuildContainerWithoutCachecommand. This instead omits the--cache-fromflag from thedockerbuildxcommand, while also adding the--no-cacheand--pullflags to prevent caching from any existing image layers, using only the latest images from a container registry.\n", + "Rebuilding without caching may be necessary when:\n", + "Specifically, for this project, volumes remain unaffected by this rebuilding process: i.e. those used to mount the ccache directory or colcon workspace. While volume management is left to the user’s discretion, other projects may of course handle this differently, so be sure to check the./devcontainerconfiguration to inspect how various container resources may be managed.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'find\\n'\n", + " '/tmp\\n'\n", + " '-type\\n'\n", + " 'f\\n'\n", + " '-path\\n'\n", + " '\"*/devcontainers-*/env-loginInteractiveShell.json\"\\n'\n", + " '-exec\\n'\n", + " '\\\\\\n'\n", + " 'jq\\n'\n", + " '-r\\n'\n", + " '\\'to_entries | .[] | \"\\\\(.key)=\\\\(.value | @sh)\"\\'\\n'\n", + " '{}\\n'\n", + " '\\\\;\\n'\n", + " '>\\n'\n", + " '.env\\n'\n", + " '\\n'\n", + " 'source\\n'\n", + " '.env\\n',\n", + " 'context': 'The environment provided byuserEnvProbecan be sourced manually. '\n", + " 'E.g. for the defaultloginInteractiveShellprobe:',\n", + " 'filename': 'loginInteractiveShell',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up the Robot’s Footprint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Footprint Introduction\n", + "The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans.\n", + "The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used.\n", + "For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization.\n", + "For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot.\n", + "Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Configuring the Robot’s Footprint\n", + "In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps.\n", + "Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot.\n", + "Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot.\n", + "For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We will now confirm that we have properly set upsam_bot’s footprint.\n", + "First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below.\n", + "After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor.\n", + "Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below.\n", + "Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors.\n", + "Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following:\n", + "We should now be able to visualize the footprints in RViz, which will be discussed in the next section.\n", + "\n", + "## Visualizing Footprint in RViz\n", + "To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot:\n", + "On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot:\n", + "\n", + "## Conclusion\n", + "In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function.\n", + "As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '188\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '189\\n'\n", + " 'footprint\\n'\n", + " ':\\n'\n", + " '\"[\\n'\n", + " '[0.21,\\n'\n", + " '0.195],\\n'\n", + " '[0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '0.195]\\n'\n", + " ']\"\\n'\n", + " '190\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Below is the code snippet fromnav2_params.yamldefining the local '\n", + " 'costmap footprint. In this configuration file, '\n", + " 'thefootprintparameter of the local costmap has already been set '\n", + " 'with a rectangular-shaped footprint. This box is centered at '\n", + " 'thebase_linkframe ofsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '232\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '233\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " '234\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': 'For the global costmap, we have already set '\n", + " 'therobot_radiusparameter to create a circular footprint that '\n", + " 'matchessam_bot’s size and centered atbase_link. The parameter '\n", + " 'that was modified is shown in the code snippet below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'First, we launchlaunch/display.launch.pyto launch the robot '\n", + " 'state publisher, spawnsam_botin Gazebo, and visualizesam_botand '\n", + " 'its footprint in Rviz. The robot state publisher publishes '\n", + " 'thebase_link=>sensorstransforms defined insam_bot’s URDF, while '\n", + " 'Gazebo’s differential drive plugin publishes '\n", + " 'theodom=>base_linktransform. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'map\\n'\n", + " 'odom\\n',\n", + " 'context': 'Next, we will publish themap=>odomtransform using '\n", + " 'thestatic_transform_publisher. We publish themap=>odomtransform '\n", + " 'as static in this guide as a simple way to publish the transform '\n", + " 'and visualize the footprint. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'navigation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '\\n',\n", + " 'context': 'Lastly, we will launch Nav2 using '\n", + " 'thenav2_params.yamlconfiguration file we just made '\n", + " 'andnavigation_launch.py, the built-in launch file '\n", + " 'ofnav2_bringup. Open a new terminal and execute the following:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dynamic Object Following\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely.\n", + "This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application:\n", + "The requirements for this task are as follows:\n", + "The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest,\n", + "send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Create the Behavior Tree\n", + "Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow:\n", + "First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node.\n", + "We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received.\n", + "To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance.\n", + "Now, you may save this behavior tree and use it in our navigation task.\n", + "For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage.\n", + "\n", + "## 1- Setup Rviz clicked point\n", + "We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to\n", + "publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone\n", + "this repo in your workspace, build, and type in a terminal.\n", + "ros2runnav2_test_utilsclicked_point_to_pose\n", + "Optionally, you can remap this topic in your rviz configuration file togoal_updates.\n", + "\n", + "## 2- Run Dynamic Object Following in Nav2 Simulation\n", + "Start Nav2 in one terminal:\n", + "ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml\n", + "Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial.\n", + "When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest!\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Let’s start from this simple behavior tree. This behavior tree '\n", + " 'replans a new path at 1 hz and passes that path to the '\n", + " 'controller to follow:',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'First, let’s make this behavior run until there’s a failure. For '\n", + " 'this purpose, we will use theKeepRunningUntilFailurecontrol '\n", + " 'node.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'We will then use the decoratorGoalUpdaterto accept updates of '\n", + " 'the dynamic object pose we’re trying to follow. This node takes '\n", + " 'as input the current goal and subscribes to the '\n", + " 'topic/goal_update. It sets the new goal asupdated_goalif a new '\n", + " 'goal on that topic is received.',\n", + " 'filename': 'updated_goal',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To stay at a certain distance from the target, we will use the '\n", + " 'action nodeTruncatePath. This node modifies a path making it '\n", + " 'shorter so we don’t try to navigate into the object of interest. '\n", + " 'We can set up the desired distance to the goal using the input '\n", + " 'portdistance.',\n", + " 'filename': 'distance',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Theta Star Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "The parameters of the planner are:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_theta_star_planner::ThetaStarPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'how_many_corners\\n'\n", + " ':\\n'\n", + " '8\\n'\n", + " 'w_euc_cost\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'w_traversal_cost\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'w_heuristic_cost\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Do go through the README file available on this repo’s link to '\n", + " 'develop a better understanding of how you could tune this '\n", + " 'planner.\\n'\n", + " 'This planner requires you to tune '\n", + " 'thecost_scaling_factorparameter of your costmap too, to get good '\n", + " 'results.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Theta Star Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "The parameters of the planner are:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_theta_star_planner::ThetaStarPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'how_many_corners\\n'\n", + " ':\\n'\n", + " '8\\n'\n", + " 'w_euc_cost\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'w_traversal_cost\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'w_heuristic_cost\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Do go through the README file available on this repo’s link to '\n", + " 'develop a better understanding of how you could tune this '\n", + " 'planner.\\n'\n", + " 'This planner requires you to tune '\n", + " 'thecost_scaling_factorparameter of your costmap too, to get good '\n", + " 'results.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Controller Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugins\n", + "When theprogress_checker_plugins,goal_checker_pluginorcontroller_pluginsparameters are not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'failure_tolerance\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " '# goal_checker_plugin: \"goal_checker\" For Galactic and older\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': '“dwb_core::DWBLocalPlanner”',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GoalDistCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": GoalDistCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: BaseObstacleCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": BaseObstacleCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Savitzky-Golay Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Savitzky-Golay Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"savitzky_golay_smoother\"\\n'\n", + " ']\\n'\n", + " 'savitzky_golay_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SavitzkyGolaySmoother\"\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Number of times to recursively smooth a segment',\n", + " 'filename': 'refinement_num',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smoother Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Smoother Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Getting Involved\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Getting Involved\n", + "If you’re interested in getting involved in Navigation 2, first of all, welcome!\n", + "We encourage everyone to get involved from students, to junior developers, to senior developers, and executives.\n", + "There’s something to do for everyone from bug fixes, to feature development, new algorithms, and refactoring.\n", + "All ROS 2 TSC Working Groups have their meetings on theworking group calendar.\n", + "Here, you can find the date and time of the Navigation2 working group meeting. Make sure you’re checking in your local timezone.\n", + "From this calendar, you can add yourself to the event so it will appear on your google calendar and get the event link to the call through Google Hangouts.\n", + "We encourage everyone interested to come to the meeting to introduce yourself, your project, and see what everyone is working on.\n", + "Further,ROS Discourseis a good place to follow larger discussions happening in the community and announcements. This isnotthe correct place to post questions or ask for assistance. Please visitROS Answersfor Q&A.\n", + "Lastly, we have aCommunity Slackwhere we chat in real-time about topics in public channels or sidebar maintainers on individual projects via PMs. If you’re interested in contributing to Nav2, this is a great place to join!\n", + "If you’re looking to contribute code or bugs, please see the Process section below.\n", + "Over time, for developers that have an interest and have shown technical competence in an area of the stack, we elevate developers to a maintainers status.\n", + "That allows push rights to our protected branches, first-reviewers rights, and getting your name onAbout and Contact.\n", + "There currently is not a clear process for getting to be a maintainer, but if you’ve been involved and contributing over a duration of several months, you may be a good candidate and should email the project lead listed onAbout and Contact.\n", + "\n", + "## Process\n", + "After you’ve introduced yourself in a working group meeting (recommended, not required), you’re ready to get started!\n", + "We recommend a typical open-source project flow and value detail and transparency.\n", + "If you commit to something and need to pull back, say so.\n", + "We all know priorities change and appreciate the heads up so that task can go into the open queue of tasks.\n", + "The process is simple and is as follow:\n", + "Note: We take code quality seriously and strive for high-quality and consistent code.\n", + "We make use of the linting and static analysis tools provided in ROS 2 (ament_cpplint,ament_uncrustify,ament_cppcheck, etc).\n", + "All PRs are built in CI with the appropriate ROS distributions and run through a set of unit and system level tests including static analysis.\n", + "You can see the results of these tests in the pull request.\n", + "It is expected for feature development for tests to cover this work to be added.\n", + "If any documentation must be updated due to your changes, that should be included in your pull request.\n", + "\n", + "## Licensing\n", + "Licensing is very important to open source projects. It helps ensure the\n", + "software continues to be available under the terms that the author\n", + "desired.\n", + "Because much of the source code is ported from other ROS 1 projects, each\n", + "package has it’s own license. Contributions should be made under the predominant\n", + "license of that package. Entirely new packages should be made available under\n", + "theApache 2.0 license.\n", + "A license tells you what rights you have as a developer, as provided by\n", + "the copyright holder. It is important that the contributor fully\n", + "understands the licensing rights and agrees to them. Sometimes the\n", + "copyright holder isn’t the contributor, such as when the contributor is\n", + "doing work on behalf of a company.\n", + "If for some reason Apache 2.0 or BSD licenses are not appropriate for your work, please get in contact with a project maintainer and discuss your concerns or requirements.\n", + "We may consider special exceptions for exceptional work, within reason (we will not accept any licenses that makes it unsuitable for commercial use).\n", + "\n", + "## Developer Certification of Origin (DCO)\n", + "To make a good faith effort to ensure licensing criteria are met,\n", + "Nav2 encourages the Developer Certificate of Origin (DCO) process\n", + "to be followed.\n", + "The DCO is an attestation attached to every contribution made by a\n", + "developer. In the commit message of the contribution, (described more\n", + "fully later in this document), the developer simply adds aSigned-off-bystatement and thereby agrees to the DCO.\n", + "In practice, its easier to justgitcommit-s-m\"commitmessage.\".\n", + "Where-sadds this automatically.\n", + "If you forgot to add this to a commit, it is easy to append via:gitcommit--amend-s.\n", + "When a developer submits a patch, it is a commitment that the\n", + "contributor has the right to submit the patch per the license. The DCO\n", + "agreement is shown below and athttp://developercertificate.org/.\n", + "\n", + "Code Blocks:\n", + "[{'code': \"Developer's Certificate of Origin 1.1\\n\"\n", + " '\\n'\n", + " 'By making a contribution to this project, I certify that:\\n'\n", + " '\\n'\n", + " '(a) The contribution was created in whole or in part by me and I\\n'\n", + " ' have the right to submit it under the open source license\\n'\n", + " ' indicated in the file; or\\n'\n", + " '\\n'\n", + " '(b) The contribution is based upon previous work that, to the\\n'\n", + " ' best of my knowledge, is covered under an appropriate open\\n'\n", + " ' source license and I have the right under that license to\\n'\n", + " ' submit that work with modifications, whether created in whole\\n'\n", + " ' or in part by me, under the same open source license (unless\\n'\n", + " ' I am permitted to submit under a different license), as\\n'\n", + " ' Indicated in the file; or\\n'\n", + " '\\n'\n", + " '(c) The contribution was provided directly to me by some other\\n'\n", + " ' person who certified (a), (b) or (c) and I have not modified\\n'\n", + " ' it.\\n'\n", + " '\\n'\n", + " '(d) I understand and agree that this project and the contribution\\n'\n", + " ' are public and that a record of the contribution (including\\n'\n", + " ' all personal information I submit with it, including my\\n'\n", + " ' sign-off) is maintained indefinitely and may be redistributed\\n'\n", + " ' consistent with this project or the open source license(s)\\n'\n", + " ' involved.\\n',\n", + " 'context': 'When a developer submits a patch, it is a commitment that the\\n'\n", + " 'contributor has the right to submit the patch per the license. '\n", + " 'The DCO\\n'\n", + " 'agreement is shown below and athttp://developercertificate.org/.',\n", + " 'filename': 'gitcommit--amend-s',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Speed Filter Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " '...\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'speed_limit_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_limit\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1',\n", + " 'context': 'Time with which to post-date the transform that is published, to '\n", + " 'indicate that this transform is valid into the future. Used when '\n", + " 'filter mask and current costmap layer are in different frames.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ClearCostmapAroundRobot\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Action server timeout (ms).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Tree XML Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Plugins\n", + "\n", + "\n", + "## Condition Plugins\n", + "\n", + "\n", + "## Control Plugins\n", + "\n", + "\n", + "## Decorator Plugins\n", + "\n", + "\n", + "## Example\n", + "This Behavior Tree replans the global path periodically at 1 Hz and it also has\n", + "recovery actions.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This Behavior Tree replans the global path periodically at 1 Hz '\n", + " 'and it also has\\n'\n", + " 'recovery actions.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DWB Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Simple Commander API\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage.\n", + "A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults).\n", + "You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints().\n", + "\n", + "## Commander API\n", + "The methods provided by the basic navigator are shown below, with inputs and expected returns.\n", + "If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype.\n", + "New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches.\n", + "\n", + "## Costmap API\n", + "This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API.\n", + "\n", + "## Footprint Collision Checker API\n", + "This is a Python3 API for a Footprint Collision Checker.\n", + "It provides the needed methods to manipulate the coordinates\n", + "and calculate the cost of a Footprint in a given map.\n", + "\n", + "## Examples and Demos\n", + "All of these can be found in thepackage.\n", + "Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user:\n", + "Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'from\\n'\n", + " 'nav2_simple_commander.robot_navigator\\n'\n", + " 'import\\n'\n", + " 'BasicNavigator\\n'\n", + " 'import\\n'\n", + " 'rclpy\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'nav\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ')\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# if autostarted, else use lifecycleStartup()\\n'\n", + " '# ...\\n'\n", + " 'path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getPath\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ',\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'smoothed_path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'smoothPath\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_duration\\n'\n", + " '>\\n'\n", + " '600\\n'\n", + " ':\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'cancelTask\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'You may use this simple commander preempt commands of the same '\n", + " 'type (e.g. you can preempt agoToPose()with anothergoToPose()) '\n", + " 'but you must explicitly cancel a current command and issue a new '\n", + " 'one if switching betweengoToPose(),goThroughPoses(), '\n", + " 'orfollowWaypoints().',\n", + " 'filename': 'followWaypoints()',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: IsStopped\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Port\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Duration (ms) the velocity must remain below the threshold',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigate Through Poses\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'While this behavior tree does not make use of it, '\n", + " 'thePlannerSelector,ControllerSelector, '\n", + " 'andGoalCheckerSelectorbehavior tree nodes can also be helpful. '\n", + " 'Rather than hardcoding the algorithm to use '\n", + " '(GridBasedandFollowPath), these behavior tree nodes will allow a '\n", + " 'user to dynamically change the algorithm used in the navigation '\n", + " 'system via a ROS topic. It may be instead advisable to create '\n", + " 'different subtree contexts using condition nodes with specified '\n", + " 'algorithms in their most useful and unique situations. However, '\n", + " 'the selector nodes can be a useful way to change algorithms from '\n", + " 'an external application rather than via internal behavior tree '\n", + " 'control flow logic. It is better to implement changes through '\n", + " 'behavior tree methods, but we understand that many professional '\n", + " 'users have external applications to dynamically change settings '\n", + " 'of their navigators.',\n", + " 'filename': 'FollowPath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Coverage Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'coverage_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'action_server_result_timeout\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'coordinates_in_cartesian_frame\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'robot_width\\n'\n", + " ':\\n'\n", + " '2.1\\n'\n", + " 'operation_width\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'min_turning_radius\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'linear_curv_change\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'default_allow_overlap\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'default_headland_width\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'default_path_continuity_type\\n'\n", + " ':\\n'\n", + " '\"CONTINUOUS\"\\n'\n", + " 'default_path_type\\n'\n", + " ':\\n'\n", + " '\"DUBINS\"\\n'\n", + " 'default_route_type\\n'\n", + " ':\\n'\n", + " '\"BOUSTROPHEDON\"\\n'\n", + " 'default_swath_angle_type\\n'\n", + " ':\\n'\n", + " '\"BRUTE_FORCE\"\\n'\n", + " 'default_swath_type\\n'\n", + " ':\\n'\n", + " '\"LENGTH\"\\n'\n", + " 'default_turn_point_distance\\n'\n", + " ':\\n'\n", + " '0.1',\n", + " 'context': 'Foropennav_row_coverage, whether to reorder the parsed rows in '\n", + " 'the order of their``id``s.',\n", + " 'filename': 'opennav_row_coverage',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: About and Contact\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## About\n", + "Navigation is a community effort to lower the barrier of entry of mobile robotics technology for all.\n", + "This project is one of the flagship projects along with MoveIt that acts as an applications entry point and frameworks for ROS.\n", + "Navigation in ROS 2 builds on the wild success of the original Navigation Stack (Nav Stack) in ROS (1).\n", + "This project has been used by researchers, educators, and industry for over 10 years.\n", + "There are very few projects that have lasted as long or were as successful as ROS (1) Navigation.\n", + "We would like to thank David Lu!! and Mike Ferguson for their tireless over the span of a decade to keep the Nav Stack alive and well.\n", + "Without their hard work, this project would not have been able to happen.\n", + "For a list of robots using Navigation2, seeRobots Using.\n", + "Aslas, as time moves on, so must we.\n", + "ROS (1) had a great run and those of us that build projects using it will remember it fondly(ish).\n", + "With change comes possibilities.\n", + "Navigation2 builds on the success but redesigns the framework to be more flexible and the feedback gathered over 10 years.\n", + "We strive to create an open community and encourage new ROS users and experts alike to collaborate.\n", + "However, that can’t happen without your issues, pull requests, and support.\n", + "Navigation, like all open-source projects, is kept going by a dedicated group of developers, maintainers, users, and collaborators.\n", + "We would like to thank here our current and past contributors and maintainers.\n", + "If you or your organization are interested in sponsoring Navigation or any work around it, please reach out to the current project lead.\n", + "Our current leadership team includes:\n", + "Our former leadership team includes:\n", + "\n", + "## Contact\n", + "If you are interested in contacting someone about Navigation, ROS 2, or related projects, please email the project leader or emailinfo@opennav.org.\n", + "We intentionally make our emails easy to find.\n", + "If your inquiry relates to bugs or open-source feature requests, consider posting a ticket on our GitHub project.\n", + "If your inquiry relates to configuration support or private feature development, reach out and we may be able to connect you with\n", + "independent consultants or contractors that know this project well.\n", + "Check out the Navigation 2Slackcommunity.\n", + "\n", + "=== Document ===\n", + "Title: WouldAControllerRecoveryHelp\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Port\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The active error code to compare against. This should match the '\n", + " 'controller server error code.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Rotation Shim Controller Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'rotate_to_goal_heading\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Primary controller params can be placed here below\\n'\n", + " '# ...',\n", + " 'context': 'If true, the rotationShimController will only rotate to heading '\n", + " 'once on a new goal, not each time a path is set.',\n", + " 'filename': 'README',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: NavFn Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'use_astar\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'allow_unknown\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'If true, the last pose of the path generated by the planner will '\n", + " 'have its orientation set to the approach orientation, i.e. the '\n", + " 'orientation of the vector connecting the last two points of the '\n", + " 'path',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior-Tree Navigator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " 'replace/with/path/to/bt.xml\\n'\n", + " '# or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " 'default_nav_through_poses_bt_xml\\n'\n", + " ':\\n'\n", + " 'replace/with/path/to/bt.xml\\n'\n", + " '# or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " 'always_reload_bt_xml\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'goal_blackboard_id\\n'\n", + " ':\\n'\n", + " 'goal\\n'\n", + " 'goals_blackboard_id\\n'\n", + " ':\\n'\n", + " 'goals\\n'\n", + " 'path_blackboard_id\\n'\n", + " ':\\n'\n", + " 'path\\n'\n", + " 'navigators\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'navigate_to_pose'\\n\"\n", + " ',\\n'\n", + " \"'navigate_through_poses'\\n\"\n", + " ']\\n'\n", + " 'navigate_to_pose\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_bt_navigator::NavigateToPoseNavigator\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'navigate_through_poses\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_bt_navigator::NavigateThroughPosesNavigator\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'plugin_lib_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'nav2_compute_path_to_pose_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_follow_path_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_back_up_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_spin_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_wait_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_clear_costmap_service_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_is_stuck_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_is_stopped_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_goal_reached_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_initial_pose_received_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_goal_updated_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_reinitialize_global_localization_service_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_rate_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_distance_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_speed_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_recovery_node_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_pipeline_sequence_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_round_robin_node_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_transform_available_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_time_expired_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_distance_traveled_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_single_trigger_bt_node\\n'\n", + " 'error_code_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code\\n'\n", + " '# - smoother_error_code, navigate_to_pose_error_code, '\n", + " 'navigate_through_poses_error_code, etc',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'NavigateThroughPoses',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "Note:dock_pluginsand eitherdocksordock_databaseare required.\n", + "\n", + "## SimpleChargingDock Parameters\n", + "Simple Charging Dock is a provided charging dock plugin that can handle many docks and common techniques.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " \"# Also 'opennav_docking::SimpleNonChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'id\\n'\n", + " ':\\n'\n", + " \"'c67f50cb-e152-4720-85cc-5eb20bd85ce8'\\n\"\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'If not using stall detection, the pose threshold to the docking '\n", + " 'pose whereisDocked()=true.',\n", + " 'filename': 'isDocked()=true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Rotation Shim Controller Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'rotate_to_goal_heading\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Primary controller params can be placed here below\\n'\n", + " '# ...',\n", + " 'context': 'If true, the rotationShimController will only rotate to heading '\n", + " 'once on a new goal, not each time a path is set.',\n", + " 'filename': 'README',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smac Hybrid-A* Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smac_planner::SmacPlannerHybrid\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'downsample_costmap\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# whether or not to downsample the map\\n'\n", + " 'downsampling_factor\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " '# multiplier for the resolution of the costmap layer (e.g. 2 on a '\n", + " '5cm costmap would be 10cm)\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " '# dist-to-goal heuristic cost (distance) for valid tolerance '\n", + " 'endpoints if exact goal cannot be found.\\n'\n", + " 'allow_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# allow traveling in unknown space\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '1000000\\n'\n", + " '# maximum total iterations to search for before failing (in case '\n", + " 'unreachable), set to -1 to disable\\n'\n", + " 'max_on_approach_iterations\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " '# Maximum number of iterations after within tolerances to continue '\n", + " 'to try to find exact solution\\n'\n", + " 'max_planning_time\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '# max time in s for planner to plan, smooth\\n'\n", + " 'motion_model_for_search\\n'\n", + " ':\\n'\n", + " '\"DUBIN\"\\n'\n", + " '# Hybrid-A* Dubin, Redds-Shepp\\n'\n", + " 'angle_quantization_bins\\n'\n", + " ':\\n'\n", + " '72\\n'\n", + " '# Number of angle bins for search\\n'\n", + " 'analytic_expansion_ratio\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " '# The ratio to attempt analytic expansions during search for final '\n", + " 'approach.\\n'\n", + " 'analytic_expansion_max_length\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '# For Hybrid/Lattice nodes: The maximum length of the analytic '\n", + " 'expansion to be considered valid to prevent unsafe shortcutting\\n'\n", + " 'analytic_expansion_max_cost\\n'\n", + " ':\\n'\n", + " '200.0\\n'\n", + " '# The maximum single cost for any part of an analytic expansion to '\n", + " 'contain and be valid, except when necessary on approach to goal\\n'\n", + " 'analytic_expansion_max_cost_override\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether or not to override the maximum cost setting if within '\n", + " 'critical distance to goal (ie probably required)\\n'\n", + " 'minimum_turning_radius\\n'\n", + " ':\\n'\n", + " '0.40\\n'\n", + " '# minimum turning radius in m of path / vehicle\\n'\n", + " 'reverse_penalty\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '# Penalty to apply if motion is reversing, must be => 1\\n'\n", + " 'change_penalty\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '# Penalty to apply if motion is changing directions (L to R), must '\n", + " 'be >= 0\\n'\n", + " 'non_straight_penalty\\n'\n", + " ':\\n'\n", + " '1.2\\n'\n", + " '# Penalty to apply if motion is non-straight, must be => 1\\n'\n", + " 'cost_penalty\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '# Penalty to apply to higher cost areas when adding into the '\n", + " 'obstacle map dynamic programming distance expansion heuristic. This '\n", + " 'drives the robot more towards the center of passages. A value '\n", + " 'between 1.3 - 3.5 is reasonable.\\n'\n", + " 'retrospective_penalty\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'lookup_table_size\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " '# Size of the dubin/reeds-sheep distance window to cache, in '\n", + " 'meters.\\n'\n", + " 'cache_obstacle_heuristic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Cache the obstacle map dynamic programming distance expansion '\n", + " 'heuristic between subsequent replannings of the same goal location. '\n", + " 'Dramatically speeds up replanning performance (40x) if costmap is '\n", + " 'largely static.\\n'\n", + " 'debug_visualizations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# For Hybrid nodes: Whether to publish expansions on the '\n", + " '/expansions topic as an array of poses (the orientation has no '\n", + " \"meaning) and the path's footprints on the /planned_footprints \"\n", + " 'topic. WARNING: heavy to compute and to display, for debug only as '\n", + " 'it degrades the performance.\\n'\n", + " 'use_quadratic_cost_penalty\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'downsample_obstacle_heuristic\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'allow_primitive_interpolation\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'smooth_path\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# If true, does a simple and quick smoothing post-processing to the '\n", + " 'path\\n'\n", + " 'smoother\\n'\n", + " ':\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'w_data\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Number of times to recursively attempt to smooth, must be>=1.',\n", + " 'filename': '>=1',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a New Nav2 Task Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Lifecycle Nodes\n", + "The Lifecycle node is the first key component of a nav2 task server. Lifecycle nodes were introduced in ROS 2 to systematically manage the bringup and shutdown of the different nodes involved in the robot’s operation. The use of Lifecycle nodes ensures that all nodes are successfully instantiated before they begin their execution and Nav2 shuts down all nodes if there is any unresponsive node.\n", + "Lifecycle nodes contain state machine transitions that enable deterministic behavior in ROS 2 servers. The Lifecycle node transitions in Nav2 are handled by theLifecycleManager. The Lifecycle Manager transitions the states of the Lifecycle nodes and provides greater control over the state of a system.\n", + "The primary states of a Lifecycle node areUnconfigured,Inactive,Active, andFinalized. A Lifecycle node starts in anUnconfiguredstate after being instantiated. The Lifecycle Manager transitions a node fromUnconfiguredtoInactiveby implementing theConfiguratingtransition. TheConfiguratingtransition sets up all configuration parameters and prepares any required setup such as memory allocation and the set up of the static publication and subscription topics. A node in theInactivestate is allowed to reconfigure its parameters and but cannot perform any processing. From theInactivestate, the Lifecycle Manager implements theActivatingtransition state to transition the node fromInactivetoActive, which is the main state. A node in theActivestate is allowed to perform any processing operation. In case a node crashes, the Lifecycle Manager shuts down the system to prevent any critical failures. On shutdown, the necessary cleanup operations are performed and the nodes are transitioned to theFinalizedstate viaDeactivating,CleaningUp, andShuttingDowntransition states.\n", + "You may wish to integrate your own nodes into the Nav2 framework or add new lifecycle nodes to your system. As an example, we will add a new notional lifecycle nodesensor_driver, and have it be controlled via the Nav2 Lifecycle Manager to ensure sensor feeds are available before activating navigation. You can do so by adding asensor_drivernode in your launch file and adding it to the list of nodes to be activated by thelifecycle_managerbefore navigation, as shown in the example below.\n", + "In the snippet above, the nodes to be handled by the Lifecycle Manager are set using thenode_namesparameter. Thenode_namesparameter takes in an ordered list of nodes to bringup through the Lifecycle transition. As shown in the snippet, thenode_namesparameter takes inlifecycle_nodeswhich contains the list of nodes to be added to the Lifecycle Manager. The Lifecycle Manager implements bringup transitions (ConfiguringandActivating) to the nodes one-by-one and in order, while the nodes are processed in reverse order for shutdown transitions. Hence, thesensor_driveris listed first before the other navigation servers so that the sensor data is available before the navigation servers are activated.\n", + "Two other parameters of the Lifecycle Manager areautostartandbond_timeout. Setautostarttotrueif you want to set the transition nodes to theActivestate on startup. Otherwise, you will need to manually trigger Lifecycle Manager to transition up the system. Thebond_timeoutsets the waiting time to decide when to transition down all of the nodes if a node is not responding.\n", + "\n", + "## Composition\n", + "Composition is the second key component nav2 task servers that was introduced to reduce the memory and CPU resources by putting multiple nodes in a single process. In Nav2, Composition can be used to compose all Nav2 nodes in a single process instead of launching them separately. This is useful for deployment on embedded systems where developers need to optimize resource usage.\n", + "In the following section, we give an example on how to add a new Nav2 server, which we notionally call theroute_server, to our system.\n", + "We make use of the launch files to compose different servers into a single process. The process is established by theComposableNodeContainercontainer that is populated with composition nodes viaComposableNode. This container can then be launched and used the same as any other Nav2 node.\n", + "\n", + "## Error codes\n", + "Your nav2 task server may also wish to return a ‘error_code’ in its action response (though not required). If there are semantically meaningful and actionable types of failures for your system, this is a systemic way to communicate those failures which may be automatically aggregated into the responses of the navigation system to your application.\n", + "It is important to note that error codes from 0-9999 are reserved for internal nav2 servers with each server offset by 100 while external servers start at 10000 and end at 65535.\n", + "The table below shows the current servers along with the expected error code structure.\n", + "Error codes are attached to the response of the action message. An example can be seen below for the route server. Note that by convention we set the error code field within the message definition toerror_code.\n", + "As stated in the message, the priority order of the errors should match the message order, 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "Since the the route server is a external server, the errors codes start at 10000 and go up to 10099.\n", + "In order to propagate your server’s error code to the rest of the system it must be added to the nav2_params.yaml file.\n", + "Theerror_code_id_namesinside of the BT Navigator define what error codes to look for on the blackboard by the server. The lowest error code of the sequence is then returned - whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "\n", + "## Conclusion\n", + "In this section of the guide, we have discussed Lifecycle Nodes, Composition and Error Codes which are new and important concepts in ROS 2. We also showed how to implement Lifecycle Nodes, Composition and Error Codes to your newly created nodes/servers with Nav2. These three concepts are helpful to efficiently run your system and therefore are encouraged to be used throughout Nav2.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'smoother_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " '...\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_navigation'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),',\n", + " 'context': 'You may wish to integrate your own nodes into the Nav2 framework '\n", + " 'or add new lifecycle nodes to your system. As an example, we '\n", + " 'will add a new notional lifecycle nodesensor_driver, and have it '\n", + " 'be controlled via the Nav2 Lifecycle Manager to ensure sensor '\n", + " 'feeds are available before activating navigation. You can do so '\n", + " 'by adding asensor_drivernode in your launch file and adding it '\n", + " 'to the list of nodes to be activated by '\n", + " 'thelifecycle_managerbefore navigation, as shown in the example '\n", + " 'below.',\n", + " 'filename': 'lifecycle_manager',\n", + " 'language': 'unknown'},\n", + " {'code': 'container\\n'\n", + " '=\\n'\n", + " 'ComposableNodeContainer\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'my_container'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rclcpp_components'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'component_container'\\n\"\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server::RouteServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " '),\\n'\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " ')',\n", + " 'context': 'Add a newComposableNode()instance in your launch file pointing '\n", + " 'to the component container of your choice.',\n", + " 'filename': 'ComposableNode()',\n", + " 'language': 'unknown'},\n", + " {'code': '\\nnav2_route_server\\n',\n", + " 'context': 'Add the package containing the server to yourpackage.xmlfile.',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '# Error codes\\n'\n", + " '# Note: The expected priority order of the errors should match the '\n", + " 'message order\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'NONE\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " '# 0 is reserved for NONE\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'UNKNOWN\\n'\n", + " '=\\n'\n", + " '10000\\n'\n", + " '# first error code in the sequence is reserved for UNKNOWN\\n'\n", + " '# User Error codes below\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'INVALID_START\\n'\n", + " '=\\n'\n", + " '10001\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'NO_VALID_ROUTE\\n'\n", + " '=\\n'\n", + " '10002\\n'\n", + " '#goal definition\\n'\n", + " '\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'goal\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'start\\n'\n", + " 'string\\n'\n", + " 'route_id\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'nav_msgs/Route\\n'\n", + " 'route\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'route_time\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '---\\n',\n", + " 'context': 'Error codes are attached to the response of the action message. '\n", + " 'An example can be seen below for the route server. Note that by '\n", + " 'convention we set the error code field within the message '\n", + " 'definition toerror_code.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'error_code_id_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'route_error_code_id',\n", + " 'context': 'In order to propagate your server’s error code to the rest of '\n", + " 'the system it must be added to the nav2_params.yaml file.\\n'\n", + " 'Theerror_code_id_namesinside of the BT Navigator define what '\n", + " 'error codes to look for on the blackboard by the server. The '\n", + " 'lowest error code of the sequence is then returned - whereas the '\n", + " 'code enums increase the higher up in the software stack - giving '\n", + " 'higher priority to lower-level failures.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Costmap 2D\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Costmap2D ROS Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thepluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Plugin Parameters\n", + "\n", + "\n", + "## Costmap Filters Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ',\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'footprint_padding\\n'\n", + " ':\\n'\n", + " '0.03\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '# radius set and used, so no footprint points\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " '# no frame set, uses frame from message\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"PointCloud2\"\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'subscribe_to_updates\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'inflate_unknown\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'inflate_around_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': '“nav2_costmap_2d::InflationLayer”',\n", + " 'filename': 'plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: TruncatePath\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The resulting truncated path.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Roadmaps\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Jazzy Roadmap\n", + "\n", + "\n", + "## Iron Roadmap\n", + "\n", + "\n", + "## Humble Roadmap\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ControllerSelector\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The output selected Controller id. This selected_controller '\n", + " 'string is usually passed to the FollowPath behavior via the '\n", + " 'controller_id input port.',\n", + " 'filename': 'transientlocal',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DockRobot\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The number of retries executed.',\n", + " 'filename': 'DockRobot',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Graceful Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Graceful Controller Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " 'nav2_graceful_controller::GracefulController\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'motion_target_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'initial_rotation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'initial_rotation_min_angle\\n'\n", + " ':\\n'\n", + " '0.75\\n'\n", + " 'final_rotation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'allow_backward\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'beta\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'lambda\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'v_angular_max\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'slowdown_radius\\n'\n", + " ':\\n'\n", + " '1.5',\n", + " 'context': 'Whether to allow the robot to move backward.',\n", + " 'filename': 'initial_rotation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ClearCostmapExceptRegion\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Action server timeout (ms).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a New Nav2 Task Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Lifecycle Nodes\n", + "The Lifecycle node is the first key component of a nav2 task server. Lifecycle nodes were introduced in ROS 2 to systematically manage the bringup and shutdown of the different nodes involved in the robot’s operation. The use of Lifecycle nodes ensures that all nodes are successfully instantiated before they begin their execution and Nav2 shuts down all nodes if there is any unresponsive node.\n", + "Lifecycle nodes contain state machine transitions that enable deterministic behavior in ROS 2 servers. The Lifecycle node transitions in Nav2 are handled by theLifecycleManager. The Lifecycle Manager transitions the states of the Lifecycle nodes and provides greater control over the state of a system.\n", + "The primary states of a Lifecycle node areUnconfigured,Inactive,Active, andFinalized. A Lifecycle node starts in anUnconfiguredstate after being instantiated. The Lifecycle Manager transitions a node fromUnconfiguredtoInactiveby implementing theConfiguratingtransition. TheConfiguratingtransition sets up all configuration parameters and prepares any required setup such as memory allocation and the set up of the static publication and subscription topics. A node in theInactivestate is allowed to reconfigure its parameters and but cannot perform any processing. From theInactivestate, the Lifecycle Manager implements theActivatingtransition state to transition the node fromInactivetoActive, which is the main state. A node in theActivestate is allowed to perform any processing operation. In case a node crashes, the Lifecycle Manager shuts down the system to prevent any critical failures. On shutdown, the necessary cleanup operations are performed and the nodes are transitioned to theFinalizedstate viaDeactivating,CleaningUp, andShuttingDowntransition states.\n", + "You may wish to integrate your own nodes into the Nav2 framework or add new lifecycle nodes to your system. As an example, we will add a new notional lifecycle nodesensor_driver, and have it be controlled via the Nav2 Lifecycle Manager to ensure sensor feeds are available before activating navigation. You can do so by adding asensor_drivernode in your launch file and adding it to the list of nodes to be activated by thelifecycle_managerbefore navigation, as shown in the example below.\n", + "In the snippet above, the nodes to be handled by the Lifecycle Manager are set using thenode_namesparameter. Thenode_namesparameter takes in an ordered list of nodes to bringup through the Lifecycle transition. As shown in the snippet, thenode_namesparameter takes inlifecycle_nodeswhich contains the list of nodes to be added to the Lifecycle Manager. The Lifecycle Manager implements bringup transitions (ConfiguringandActivating) to the nodes one-by-one and in order, while the nodes are processed in reverse order for shutdown transitions. Hence, thesensor_driveris listed first before the other navigation servers so that the sensor data is available before the navigation servers are activated.\n", + "Two other parameters of the Lifecycle Manager areautostartandbond_timeout. Setautostarttotrueif you want to set the transition nodes to theActivestate on startup. Otherwise, you will need to manually trigger Lifecycle Manager to transition up the system. Thebond_timeoutsets the waiting time to decide when to transition down all of the nodes if a node is not responding.\n", + "\n", + "## Composition\n", + "Composition is the second key component nav2 task servers that was introduced to reduce the memory and CPU resources by putting multiple nodes in a single process. In Nav2, Composition can be used to compose all Nav2 nodes in a single process instead of launching them separately. This is useful for deployment on embedded systems where developers need to optimize resource usage.\n", + "In the following section, we give an example on how to add a new Nav2 server, which we notionally call theroute_server, to our system.\n", + "We make use of the launch files to compose different servers into a single process. The process is established by theComposableNodeContainercontainer that is populated with composition nodes viaComposableNode. This container can then be launched and used the same as any other Nav2 node.\n", + "\n", + "## Error codes\n", + "Your nav2 task server may also wish to return a ‘error_code’ in its action response (though not required). If there are semantically meaningful and actionable types of failures for your system, this is a systemic way to communicate those failures which may be automatically aggregated into the responses of the navigation system to your application.\n", + "It is important to note that error codes from 0-9999 are reserved for internal nav2 servers with each server offset by 100 while external servers start at 10000 and end at 65535.\n", + "The table below shows the current servers along with the expected error code structure.\n", + "Error codes are attached to the response of the action message. An example can be seen below for the route server. Note that by convention we set the error code field within the message definition toerror_code.\n", + "As stated in the message, the priority order of the errors should match the message order, 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "Since the the route server is a external server, the errors codes start at 10000 and go up to 10099.\n", + "In order to propagate your server’s error code to the rest of the system it must be added to the nav2_params.yaml file.\n", + "Theerror_code_id_namesinside of the BT Navigator define what error codes to look for on the blackboard by the server. The lowest error code of the sequence is then returned - whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "\n", + "## Conclusion\n", + "In this section of the guide, we have discussed Lifecycle Nodes, Composition and Error Codes which are new and important concepts in ROS 2. We also showed how to implement Lifecycle Nodes, Composition and Error Codes to your newly created nodes/servers with Nav2. These three concepts are helpful to efficiently run your system and therefore are encouraged to be used throughout Nav2.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'smoother_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " '...\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_navigation'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),',\n", + " 'context': 'You may wish to integrate your own nodes into the Nav2 framework '\n", + " 'or add new lifecycle nodes to your system. As an example, we '\n", + " 'will add a new notional lifecycle nodesensor_driver, and have it '\n", + " 'be controlled via the Nav2 Lifecycle Manager to ensure sensor '\n", + " 'feeds are available before activating navigation. You can do so '\n", + " 'by adding asensor_drivernode in your launch file and adding it '\n", + " 'to the list of nodes to be activated by '\n", + " 'thelifecycle_managerbefore navigation, as shown in the example '\n", + " 'below.',\n", + " 'filename': 'lifecycle_manager',\n", + " 'language': 'unknown'},\n", + " {'code': 'container\\n'\n", + " '=\\n'\n", + " 'ComposableNodeContainer\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'my_container'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rclcpp_components'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'component_container'\\n\"\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server::RouteServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " '),\\n'\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " ')',\n", + " 'context': 'Add a newComposableNode()instance in your launch file pointing '\n", + " 'to the component container of your choice.',\n", + " 'filename': 'ComposableNode()',\n", + " 'language': 'unknown'},\n", + " {'code': '\\nnav2_route_server\\n',\n", + " 'context': 'Add the package containing the server to yourpackage.xmlfile.',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '# Error codes\\n'\n", + " '# Note: The expected priority order of the errors should match the '\n", + " 'message order\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'NONE\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " '# 0 is reserved for NONE\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'UNKNOWN\\n'\n", + " '=\\n'\n", + " '10000\\n'\n", + " '# first error code in the sequence is reserved for UNKNOWN\\n'\n", + " '# User Error codes below\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'INVALID_START\\n'\n", + " '=\\n'\n", + " '10001\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'NO_VALID_ROUTE\\n'\n", + " '=\\n'\n", + " '10002\\n'\n", + " '#goal definition\\n'\n", + " '\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'goal\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'start\\n'\n", + " 'string\\n'\n", + " 'route_id\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'nav_msgs/Route\\n'\n", + " 'route\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'route_time\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '---\\n',\n", + " 'context': 'Error codes are attached to the response of the action message. '\n", + " 'An example can be seen below for the route server. Note that by '\n", + " 'convention we set the error code field within the message '\n", + " 'definition toerror_code.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'error_code_id_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'route_error_code_id',\n", + " 'context': 'In order to propagate your server’s error code to the rest of '\n", + " 'the system it must be added to the nav2_params.yaml file.\\n'\n", + " 'Theerror_code_id_namesinside of the BT Navigator define what '\n", + " 'error codes to look for on the blackboard by the server. The '\n", + " 'lowest error code of the sequence is then returned - whereas the '\n", + " 'code enums increase the higher up in the software stack - giving '\n", + " 'higher priority to lower-level failures.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Groot - Interacting with Behavior Trees\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Grootis the companion application of theBehaviorTree.CPPlibrary used to create, edit, and visualize behavior trees.\n", + "Behavior Trees are deeply integrated into Nav2, used as the main method of orchestrating task server logic across a complex navigation and autonomy stack.\n", + "Behavior Trees, in short BTs, consist of many nodes completing different tasks and control the flow of logic, similar to a Hierarchical or Finite State Machine, but organized in a tree structure.\n", + "These nodes are of types:Action,Condition,Control, orDecorator, and are described in more detail inNavigation ConceptsandBehaviorTree.CPP.\n", + "Writing a New Behavior Tree Pluginoffers a well written example of creating a simpleActionnode if creating new BT nodes is of interest. This tutorial will focus solely on launching Groot, visualizing a Behavior Tree, and modifying that tree for a given customization, assuming a library of BT nodes. Luckily, Nav2 provides a robust number of BT nodes for your use out of the box, enumerated inNavigation Plugins.\n", + "A BT configuration file in BehaviorTree.CPP is an XML file. This is used to dynamically load the BT node plugins at run-time from the appropriate libraries mapped to their names. The XML format is definedin detail here. Therefore, Groot needs to have a list of nodes it has access to and important metadata about them like their type and ports (or parameters). We refer to this as the “palette” of nodes later in the tutorial.\n", + "In the video above you can see Groot side-by-side with RVIz and a test platform 100% equipped with ROS-enabled hardware from SIEMENS.\n", + "Groot not only displays the current Behavior Tree while the robot is operating. Note: Before ROS 2 Humble, live Groot behavior tree monitoring during execution was supported in Nav2. This was removed due to buggy support in BT.CPP / Groot for changing behavior trees on the fly, seeGalactic to Humblefor more details.\n", + "\n", + "## Visualize Behavior Trees\n", + "To display a Behavior Tree like that inFigure 3, we will first start the Groot executable.\n", + "Out of the box, Groot can only display Behavior Trees and nodes that are from the defaults in BT.CPP, since it does not know anything about Nav2 or your other projects.\n", + "Therefore, we must point Groot to our palette, or index, of Nav2 / custom behavior tree nodes:\n", + "If you select the default treenavigate_w_replanning_and_recovery.xml, then a Groot editor should look likeFigure 3.\n", + "\n", + "## Edit Behavior Trees\n", + "Now that you have a Nav2 BT open in Groot in editor mode, you should be able to trivially modify it using the GUI.\n", + "Starting from a screen like that shown inFigure 3, you can pull in new nodes from the side panel to add them to the workspace.\n", + "You may then connect the nodes using a “drag and drop” motion between the node’s input and output ports to assemble the new nodes into the tree.\n", + "If you select a given node, you can change metadata about it such as its name or values of parameterizable ports. When you’re done modifying, simply save the new configuration file and use that on your robot the next time!\n", + "\n", + "## Adding A Custom Node\n", + "Each node in the behavior tree holds a specialized function.\n", + "Sometimes, its useful to create new nodes and add them to your palette during the design process - perhaps before the implementations themselves exist.\n", + "This helps designers abstract away the implementation specifics of the nodes from the higher level logic of the tree itself and how they’d like to interact with a given node (e.g. type, ports, etc).\n", + "Within Groot, you may create new custom nodes to add to your tree and export these new nodes back to your palette.\n", + "Implementing the node itself needs to be done separately from Groot, which is described inWriting a New Behavior Tree Plugin.\n", + "Creating a new custom node can be started by clicking the orange marked icon inFigure 4, while Groot is in Editor mode.\n", + "This should load a new window, similar toFigure 5.\n", + "In this new window, it asks you to fill in the metadata about this new node, in order to create it.\n", + "It will ask you for standard information such as name (green box), type of node (orange box), and any optional ports for parameterization or access to blackboard variables (blue box).\n", + "After completing, selectOKinFigure 5, the new custom node should appear in blue in theTreeNode Paletteas inFigure 6.\n", + "Before starting to create a new BT based on the new custom nodes, it is recommend to export the newly created nodes to save in case of Groot crashing.\n", + "This can be performed with the icon highlighted in green fromFigure 6.\n", + "The resulting XML output from the node created inFigure 5can be seen below.\n", + "You can see more examples inNav2’s BT Node Palette XML.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'coffee\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Sense\\n'\n", + " 'of\\n'\n", + " 'life\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rolling\\n'\n", + " 'target\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Before starting to create a new BT based on the new custom '\n", + " 'nodes, it is recommend to export the newly created nodes to save '\n", + " 'in case of Groot crashing.\\n'\n", + " 'This can be performed with the icon highlighted in green '\n", + " 'fromFigure 6.\\n'\n", + " 'The resulting XML output from the node created inFigure 5can be '\n", + " 'seen below.\\n'\n", + " 'You can see more examples inNav2’s BT Node Palette XML.',\n", + " 'filename': 'Action',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Provided Nodes\n", + "The nodes listed below are inside thenav2_collision_monitorpackage. See the pages for individual configuration information.\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Theta Star Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "The parameters of the planner are:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_theta_star_planner::ThetaStarPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'how_many_corners\\n'\n", + " ':\\n'\n", + " '8\\n'\n", + " 'w_euc_cost\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'w_traversal_cost\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'w_heuristic_cost\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Do go through the README file available on this repo’s link to '\n", + " 'develop a better understanding of how you could tune this '\n", + " 'planner.\\n'\n", + " 'This planner requires you to tune '\n", + " 'thecost_scaling_factorparameter of your costmap too, to get good '\n", + " 'results.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: RateController\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Rate to throttle an action or a group of actions.',\n", + " 'filename': 'GoalReached',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: InitialPoseReceived\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Success if the value in the port is true. Takes in a blackboard '\n", + " 'variable,\\n'\n", + " '“{initial_pose_received}” if not specified.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Odometry Calibration\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This behavior tree drives the robot in a CCW square three times '\n", + " 'using the DriveOnHeading and Spin behaviors.\\n'\n", + " 'The robot will traverse each side of the square at 0.2 (m/s) for '\n", + " '2 meters before making a 90 degree turn.\\n'\n", + " 'This is a primitive experiment to measure odometric accuracy and '\n", + " 'can be used and repeated to tune parameters related to odometry '\n", + " 'to improve quality.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DriveOnHeading\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Drive on heading error code. SeeDriveOnHeadingaction message for '\n", + " 'the enumerated set of error codes.',\n", + " 'filename': 'DriveOnHeading',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: ComputePathToPose\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Compute path to pose error code. SeeComputePathToPoseaction '\n", + " 'message for the enumerated set of error codes.',\n", + " 'filename': 'ComputePathToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: WaitAtWaypoint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_waypoint_follower plugin name defined in thewaypoint_task_executor_plugin_idparameter inWaypoint Follower.\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Constrained smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Smoother Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"SmoothPath\"\\n'\n", + " ']\\n'\n", + " 'SmoothPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_constrained_smoother/ConstrainedSmoother\"\\n'\n", + " 'reversing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to detect forward/reverse direction and cusps. Should be '\n", + " 'set to false for paths without orientations assigned\\n'\n", + " 'path_downsampling_factor\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '# every n-th node of the path is taken. Useful for speed-up\\n'\n", + " 'path_upsampling_factor\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " '# 0 - path remains downsampled, 1 - path is upsampled back to '\n", + " 'original granularity using cubic bezier, 2... - more upsampling\\n'\n", + " 'keep_start_orientation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to prevent the start orientation from being smoothed\\n'\n", + " 'keep_goal_orientation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to prevent the gpal orientation from being smoothed\\n'\n", + " 'minimum_turning_radius\\n'\n", + " ':\\n'\n", + " '0.40\\n'\n", + " '# minimum turning radius the robot can perform. Can be set to 0.0 '\n", + " '(or w_curve can be set to 0.0 with the same effect) for '\n", + " 'diff-drive/holonomic robots\\n'\n", + " 'w_curve\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# weight to enforce minimum_turning_radius\\n'\n", + " 'w_dist\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '# weight to bind path to original as optional replacement for cost '\n", + " 'weight\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '2000000.0\\n'\n", + " '# weight to maximize smoothness of path\\n'\n", + " 'w_cost\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " '# weight to steer robot away from collision and cost\\n'\n", + " '# Parameters used to improve obstacle avoidance near cusps '\n", + " '(forward/reverse movement changes)\\n'\n", + " 'w_cost_cusp_multiplier\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '# option to use higher weight during forward/reverse direction '\n", + " 'change which is often accompanied with dangerous rotations\\n'\n", + " 'cusp_zone_length\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '# length of the section around cusp in which nodes use '\n", + " 'w_cost_cusp_multiplier (w_cost rises gradually inside the zone '\n", + " 'towards the cusp point, whose costmap weight eqals '\n", + " 'w_cost*w_cost_cusp_multiplier)\\n'\n", + " '# Points in robot frame to grab costmap values from. Format: [x1, '\n", + " 'y1, weight1, x2, y2, weight2, ...]\\n'\n", + " '# IMPORTANT: Requires much higher number of iterations to actually '\n", + " 'improve the path. Uncomment only if you really need it (highly '\n", + " 'elongated/asymmetric robots)\\n'\n", + " '# cost_check_points: [-0.185, 0.0, 1.0]\\n'\n", + " 'optimizer\\n'\n", + " ':\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '70\\n'\n", + " '# max iterations of smoother\\n'\n", + " 'debug_optimizer\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# print debug info\\n'\n", + " 'gradient_tol\\n'\n", + " ':\\n'\n", + " '5e3\\n'\n", + " 'fn_tol\\n'\n", + " ':\\n'\n", + " '1.0e-15\\n'\n", + " 'param_tol\\n'\n", + " ':\\n'\n", + " '1.0e-20',\n", + " 'context': 'Parameter tolerance optimization termination criterion',\n", + " 'filename': 'DENSE_QR',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Transformations\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Transforms Introduction\n", + "Many ROS packages require the transform tree of a robot to be published using the TF2 ROS package. A transformation tree defines the relations between different coordinate systems, in terms of translation, rotation, and relative motion. To make this more concrete, let us apply an example of a simple robot that has a mobile base with a single laser sensor mounted on top of it.\n", + "This robot has two defined coordinate frames: one corresponding to the center point of the mobile base of the robot, and one for the center point of the laser that is mounted on top of the base. We’ll call the coordinate frame attached to the mobile basebase_linkand we’ll call the coordinate frame attached to the laserbase_laser. Note that will be talking more about the naming and conventions of these coordinate frames in the next section.\n", + "At this point, let’s assume that we have some data from the laser in the form of distance measurements from the laser’s center point. In other words, we have some data in thebase_lasercoordinate frame.\n", + "Now, suppose we want to take this data and use it to help the mobile base avoid obstacles in the world. To do this successfully, we need a way to transform the laser scan we’ve received from thebase_laserframe to thebase_linkframe. In essence, we need to define a relationship between thebase_laserandbase_linkcoordinate frames.\n", + "In defining this relationship, let us assume that the only data we have is that the laser is mounted 10cm forward and 20cm above the center point of the mobile base. This gives us a translational offset that relates thebase_linkframe to thebase_laserframe. Specifically, we know that to get data from thebase_linkframe to thebase_laserframe, we must apply a translation of (x: 0.1m, y: 0.0m, z: 0.2m), and transversely, to get data from thebase_laserframe to thebase_linkframe, we must apply the opposite translation (x: -0.1m, y: 0.0m, z: -0.20m).\n", + "We could choose to manage this relationship ourselves, meaning to store and apply the appropriate translations between the frames when necessary, but this becomes a real pain as the number of coordinate frames increases. Luckily, we don’t have to do this work ourselves. Instead, we’ll define the relationship betweenbase_linkandbase_laseronce using TF2 and let it manage the transformation between the two coordinate frames for us. This is especially useful when working with non-static transformations, such as a set of frames that are moving relative to each other, like a robot base frame in a map frame.\n", + "To define and store the relationship between thebase_linkandbase_laserframes using TF2, we need to add them to a transform tree. Conceptually, each node in the transform tree corresponds to a coordinate frame, and each edge corresponds to the transform that needs to be applied to move from the current node to its child. TF2 uses a tree structure to guarantee that there is only a single traversal that links any two coordinate frames together, and assumes that all edges in the tree are directed from parent to child nodes.\n", + "To create a transform tree for our simple example, we’ll create two nodes: one for thebase_linkcoordinate frame and one for thebase_lasercoordinate frame. To create the edge between them, we first need to decide which node will be the parent and which will be the child. Remember — this distinction is important because TF2 assumes that all transforms move from parent to child.\n", + "Let’s choose thebase_linkcoordinate frame as the parent because when other pieces/sensors are added to the robot, it will make the most sense for them to relate to thebase_laserframe by traversing through thebase_linkframe. This means that the transform associated with the edge connectingbase_linkandbase_lasershould be (x: 0.1m, y: 0.0m, z: 0.2m).\n", + "With this transform tree set up, converting the laser scan received in thebase_laserframe to thebase_linkframe is as simple as making a call to the TF2 library. Our robot can now use this information to reason about laser scans in thebase_linkframe and safely plan around obstacles in its environment.\n", + "\n", + "## Static Transform Publisher Demo\n", + "Now let’s try publishing a very simple transform using the static_transform_publisher tool provided by TF2. We will be publishing a transformation from the linkbase_linkto the linkbase_laserwith a translation of (x: 0.1m, y: 0.0m, z: 0.2m). Note that we will be building the transform from the diagram earlier in this tutorial.\n", + "Open up your command line and execute the following command:\n", + "With this, we are now successfully publishing ourbase_linktobase_lasertransform in TF2. Let us now check if it is working properly throughtf2_echo. Open up a separate command line window and execute the following:\n", + "You should be able to observe a repeated output similar to the one below.\n", + "And that’s it for this short demo - we were able to successfully publish a transform frombase_linktobase_laserusing the TF2 library. Note that we do not recommend using the above demo in publishing transforms for your actual robotics projects, it is just a quick demo to see TF2 in action. For a real robot system, we would create a URDF file which embeds this information and more about your robot for use of the robot_state_publisher rather than the static_transform_publisher. There are more suitable and practical ways to go about this which will be discussed in theSetting Up The URDFtutorial.\n", + "\n", + "## Transforms in Navigation2\n", + "There are two important ROS REPs which we highly suggest for you to check out. These documents detail some standards set about by the ROS community to ensure proper operation across different packages. Nav2 also adheres to these standards and conventions.\n", + "To quickly summarize REP 105, this document specifies the naming conventions and semantic meanings of the different coordinate frames used in ROS. Of interest to this tutorial are thebase_link,odomandmapcoordinate frames. Thebase_linkis a coordinate frame that is attached to a fixed position on the robot, typically at its main chassis and its rotational center. Theodomcoordinate frame is a fixed frame relative to the robot’s starting position and is mainly used for locally-consistent representations of distances. Lastly, themapcoordinate frame is a world fixed frame that is used for globally-consistent representations of distances.\n", + "REP 103, on the other hand, discusses some standard units of measure and other related conventions to keep integration issues between different ROS packages to a minimum. The basic overview is that frames are defined using the right hand rule, with Z up and X forward, and units should be standard SI units.\n", + "Now let’s move on to some specifics for the Navigation2 package to function correctly. Nav2 requires the following transformations to be published in ROS:\n", + "The first transformmap=>odomis usually provided by a different ROS package dealing with localization and mapping such as AMCL. This transform updates live in use so we don’t set static values for this in our robot’s TF tree. Further detail about how to set this up may be pretty complex, so we highly suggest to have a look at the documentation of the mapping or localization package you are using for your platform. All ROS compliant SLAM and localization packages will provide you with this transformation automatically on launch.\n", + "Theodom=>base_linkis usually published by our odometry system using sensors such as wheel encoders. This is typically computed via sensor fusion of odometry sensors (IMU, wheel encoders, VIO, etc) using therobot_localizationpackage.\n", + "All other statically defined transforms (e.g.base_link=>base_laser,base_link=>wheels,wheels=>IMU, etc) is what we will be talking about for the rest of this guide. This transformation tree is used by Nav2 to properly relate the information from sensors or other frame of interest to the rest of the robot. The transformation between these two coordinate frames is usually provided to Nav2 through the Robot State Publisher and the Universal Robot Descriptor File (URDF). In cases where there are more sensor coordinate frames on your platform, then a transform tree frombase_linkto each sensor coordinate frame needs to be published.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed about the concept of transforms and how they are used in Nav2.\n", + "In the last section, we have also explored using the static_transform_publisher of TF2 to publish our transforms. You may use this to set up your transforms for Nav2, but this is generally not the best way to do it. In most robotics projects, we make use of the Robot State Publisher since it is much easier to use and scales well as our robot gets more complex. We will be talking about the Robot State Publisher, URDF, and how to set it up in the next tutorial onSetting Up The URDF.\n", + "Lastly, we also discussed the three published transform requirements of Nav2 and the necessary REPs to keep in mind when setting them up.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '.1\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '.2\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'base_link\\n'\n", + " 'base_laser\\n',\n", + " 'context': 'Open up your command line and execute the following command:',\n", + " 'filename': 'base_laser',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nbase_link\\nbase_laser\\n',\n", + " 'context': 'With this, we are now successfully publishing '\n", + " 'ourbase_linktobase_lasertransform in TF2. Let us now check if it '\n", + " 'is working properly throughtf2_echo. Open up a separate command '\n", + " 'line window and execute the following:',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '0\\n'\n", + " '.0\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.100,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.200\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '1\\n'\n", + " '.000\\n'\n", + " ']',\n", + " 'context': 'You should be able to observe a repeated output similar to the '\n", + " 'one below.',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DistanceTraveled\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# other bt_navigator parameters\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1',\n", + " 'context': 'Defined and declared inBehavior-Tree Navigator.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'Robot base frame.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: SmoothPath\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Follow smoother error code. SeeSmoothPathaction for the '\n", + " 'enumerated set of error code definitions.',\n", + " 'filename': 'SmoothPath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: SingleTrigger\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n\\n',\n", + " 'context': 'This node triggers its child only once and returns FAILURE for '\n", + " 'every succeeding tick.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: TruncatePathLocal\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The resulting truncated path.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior-Tree Navigator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " 'replace/with/path/to/bt.xml\\n'\n", + " '# or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " 'default_nav_through_poses_bt_xml\\n'\n", + " ':\\n'\n", + " 'replace/with/path/to/bt.xml\\n'\n", + " '# or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " 'always_reload_bt_xml\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'goal_blackboard_id\\n'\n", + " ':\\n'\n", + " 'goal\\n'\n", + " 'goals_blackboard_id\\n'\n", + " ':\\n'\n", + " 'goals\\n'\n", + " 'path_blackboard_id\\n'\n", + " ':\\n'\n", + " 'path\\n'\n", + " 'navigators\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'navigate_to_pose'\\n\"\n", + " ',\\n'\n", + " \"'navigate_through_poses'\\n\"\n", + " ']\\n'\n", + " 'navigate_to_pose\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_bt_navigator::NavigateToPoseNavigator\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'navigate_through_poses\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_bt_navigator::NavigateThroughPosesNavigator\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'plugin_lib_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'nav2_compute_path_to_pose_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_follow_path_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_back_up_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_spin_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_wait_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_clear_costmap_service_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_is_stuck_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_is_stopped_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_goal_reached_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_initial_pose_received_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_goal_updated_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_reinitialize_global_localization_service_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_rate_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_distance_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_speed_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_recovery_node_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_pipeline_sequence_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_round_robin_node_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_transform_available_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_time_expired_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_distance_traveled_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_single_trigger_bt_node\\n'\n", + " 'error_code_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code\\n'\n", + " '# - smoother_error_code, navigate_to_pose_error_code, '\n", + " 'navigate_through_poses_error_code, etc',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'NavigateThroughPoses',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build Troubleshooting Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Common Nav2 Dependencies Build Failures\n", + "Still can’t solve it? Let us know about your issue.Open a ticket.\n", + "\n", + "## Reporting Issue\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Dynamic Object Following\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely.\n", + "This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application:\n", + "The requirements for this task are as follows:\n", + "The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest,\n", + "send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Create the Behavior Tree\n", + "Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow:\n", + "First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node.\n", + "We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received.\n", + "To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance.\n", + "Now, you may save this behavior tree and use it in our navigation task.\n", + "For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage.\n", + "\n", + "## 1- Setup Rviz clicked point\n", + "We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to\n", + "publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone\n", + "this repo in your workspace, build, and type in a terminal.\n", + "ros2runnav2_test_utilsclicked_point_to_pose\n", + "Optionally, you can remap this topic in your rviz configuration file togoal_updates.\n", + "\n", + "## 2- Run Dynamic Object Following in Nav2 Simulation\n", + "Start Nav2 in one terminal:\n", + "ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml\n", + "Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial.\n", + "When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest!\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Let’s start from this simple behavior tree. This behavior tree '\n", + " 'replans a new path at 1 hz and passes that path to the '\n", + " 'controller to follow:',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'First, let’s make this behavior run until there’s a failure. For '\n", + " 'this purpose, we will use theKeepRunningUntilFailurecontrol '\n", + " 'node.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'We will then use the decoratorGoalUpdaterto accept updates of '\n", + " 'the dynamic object pose we’re trying to follow. This node takes '\n", + " 'as input the current goal and subscribes to the '\n", + " 'topic/goal_update. It sets the new goal asupdated_goalif a new '\n", + " 'goal on that topic is received.',\n", + " 'filename': 'updated_goal',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To stay at a certain distance from the target, we will use the '\n", + " 'action nodeTruncatePath. This node modifies a path making it '\n", + " 'shorter so we don’t try to navigate into the object of interest. '\n", + " 'We can set up the desired distance to the goal using the input '\n", + " 'portdistance.',\n", + " 'filename': 'distance',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Loopback Simulator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'loopback_simulator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'map_frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'scan_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_scan\"\\n'\n", + " \"# tb4_loopback_simulator.launch.py remaps to 'rplidar_link'\\n\"\n", + " 'update_duration\\n'\n", + " ':\\n'\n", + " '0.02',\n", + " 'context': 'Whether or not to publish simulated clock to/clock',\n", + " 'filename': '/clock',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Static Layer Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: SpeedController\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Vector of goals to check. Takes in a blackboard variable, '\n", + " '“{goals}” if not specified.',\n", + " 'filename': 'GoalReached',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Commander API\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage.\n", + "A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults).\n", + "You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints().\n", + "\n", + "## Commander API\n", + "The methods provided by the basic navigator are shown below, with inputs and expected returns.\n", + "If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype.\n", + "New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches.\n", + "\n", + "## Costmap API\n", + "This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API.\n", + "\n", + "## Footprint Collision Checker API\n", + "This is a Python3 API for a Footprint Collision Checker.\n", + "It provides the needed methods to manipulate the coordinates\n", + "and calculate the cost of a Footprint in a given map.\n", + "\n", + "## Examples and Demos\n", + "All of these can be found in thepackage.\n", + "Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user:\n", + "Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'from\\n'\n", + " 'nav2_simple_commander.robot_navigator\\n'\n", + " 'import\\n'\n", + " 'BasicNavigator\\n'\n", + " 'import\\n'\n", + " 'rclpy\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'nav\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ')\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# if autostarted, else use lifecycleStartup()\\n'\n", + " '# ...\\n'\n", + " 'path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getPath\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ',\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'smoothed_path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'smoothPath\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_duration\\n'\n", + " '>\\n'\n", + " '600\\n'\n", + " ':\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'cancelTask\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'You may use this simple commander preempt commands of the same '\n", + " 'type (e.g. you can preempt agoToPose()with anothergoToPose()) '\n", + " 'but you must explicitly cancel a current command and issue a new '\n", + " 'one if switching betweengoToPose(),goThroughPoses(), '\n", + " 'orfollowWaypoints().',\n", + " 'filename': 'followWaypoints()',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use.\n", + "Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package.\n", + "\n", + "## What is the Rotation Shim Controller?\n", + "This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers.\n", + "Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so.\n", + "Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task.\n", + "TheRotationShimControlleris most suitable for:\n", + "\n", + "## Configuring Rotation Shim Controller\n", + "This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through.\n", + "As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel.\n", + "The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted.\n", + "\n", + "## Configuring Primary Controller\n", + "There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity).\n", + "An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform.\n", + "\n", + "## Demo Execution\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'As such, its configuration looks very similar to that of any '\n", + " 'other plugin. In the code block below, you can see that we’ve '\n", + " 'added theRotationShimControlleras the plugin for path tracking '\n", + " 'in the controller server. You can see that we’ve also configured '\n", + " 'it below with its internal '\n", + " 'parameters,angular_dist_thresholdthroughmax_angular_accel.',\n", + " 'filename': 'max_angular_accel',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# DWB parameters\\n'\n", + " '...\\n'\n", + " '...\\n'\n", + " '...',\n", + " 'context': 'There is one more remaining parameter of '\n", + " 'theRotationShimControllernot mentioned above, '\n", + " 'theprimary_controller. This is the type of controller that your '\n", + " 'application would like to use as the primary modus operandi. It '\n", + " 'will share the same name and yaml namespace as the shim plugin. '\n", + " 'You can observe this below with the primary controller set '\n", + " 'theDWB(with the progress and goal checkers removed for brevity).',\n", + " 'filename': 'DWB',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Savitzky-Golay Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Savitzky-Golay Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"savitzky_golay_smoother\"\\n'\n", + " ']\\n'\n", + " 'savitzky_golay_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SavitzkyGolaySmoother\"\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Number of times to recursively smooth a segment',\n", + " 'filename': 'refinement_num',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Obstacle Layer Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Dynamic Object Following\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely.\n", + "This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application:\n", + "The requirements for this task are as follows:\n", + "The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest,\n", + "send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Create the Behavior Tree\n", + "Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow:\n", + "First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node.\n", + "We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received.\n", + "To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance.\n", + "Now, you may save this behavior tree and use it in our navigation task.\n", + "For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage.\n", + "\n", + "## 1- Setup Rviz clicked point\n", + "We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to\n", + "publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone\n", + "this repo in your workspace, build, and type in a terminal.\n", + "ros2runnav2_test_utilsclicked_point_to_pose\n", + "Optionally, you can remap this topic in your rviz configuration file togoal_updates.\n", + "\n", + "## 2- Run Dynamic Object Following in Nav2 Simulation\n", + "Start Nav2 in one terminal:\n", + "ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml\n", + "Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial.\n", + "When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest!\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Let’s start from this simple behavior tree. This behavior tree '\n", + " 'replans a new path at 1 hz and passes that path to the '\n", + " 'controller to follow:',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'First, let’s make this behavior run until there’s a failure. For '\n", + " 'this purpose, we will use theKeepRunningUntilFailurecontrol '\n", + " 'node.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'We will then use the decoratorGoalUpdaterto accept updates of '\n", + " 'the dynamic object pose we’re trying to follow. This node takes '\n", + " 'as input the current goal and subscribes to the '\n", + " 'topic/goal_update. It sets the new goal asupdated_goalif a new '\n", + " 'goal on that topic is received.',\n", + " 'filename': 'updated_goal',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To stay at a certain distance from the target, we will use the '\n", + " 'action nodeTruncatePath. This node modifies a path making it '\n", + " 'shorter so we don’t try to navigate into the object of interest. '\n", + " 'We can set up the desired distance to the goal using the input '\n", + " 'portdistance.',\n", + " 'filename': 'distance',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Tree XML Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Plugins\n", + "\n", + "\n", + "## Condition Plugins\n", + "\n", + "\n", + "## Control Plugins\n", + "\n", + "\n", + "## Decorator Plugins\n", + "\n", + "\n", + "## Example\n", + "This Behavior Tree replans the global path periodically at 1 Hz and it also has\n", + "recovery actions.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This Behavior Tree replans the global path periodically at 1 Hz '\n", + " 'and it also has\\n'\n", + " 'recovery actions.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smac Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Description\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. It uses template node types to develop different search-based planners.\n", + "We support circular differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support car-like (ackermann) and legged vehicles using theSmacPlannerHybridplugin which implements a Hybrid-A* planner. We support non-circular, arbitrary shaped, any model vehicles using theSmacPlannerLatticeplugin which implements a State Lattice planner (e.g. omni, diff, ackermann, legged, custom). It contains control sets and generators for ackermann, legged, differential drive and omnidirectional vehicles, but you may provide your own for another robot type or to have different planning behaviors.\n", + "The last two plugins are bothkinematically feasibleand supportreversing. They have performance similar to its 2D counter parts like 2D-A* and NavFn via highly optimized heuristic functions and efficient programming. An example of the 3 planners can be seen below, planning a roughly 75 m path.\n", + "Usual planning times are below 100ms for some environments, occasionally approaching up to 200ms. The performance of all 3 planners is roughly comparable with naive 2D search algorithms that have long been mainstays of the ROS Navigation ecosystem, but also achieving kinematic feasibility, support for reversing, and using modern state of the art techniques.\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ReinitializeGlobalLocalization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Map Server / Saver\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Map Saver Parameters\n", + "\n", + "\n", + "## Map Server Parameters\n", + "\n", + "\n", + "## Costmap Filter Info Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'map_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"turtlebot3_world.yaml\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'map_saver\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'save_map_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'free_thresh_default\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'occupied_thresh_default\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'filter_space_value=base+multiplier*mask_value',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "Note:dock_pluginsand eitherdocksordock_databaseare required.\n", + "\n", + "## SimpleChargingDock Parameters\n", + "Simple Charging Dock is a provided charging dock plugin that can handle many docks and common techniques.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " \"# Also 'opennav_docking::SimpleNonChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'id\\n'\n", + " ':\\n'\n", + " \"'c67f50cb-e152-4720-85cc-5eb20bd85ce8'\\n\"\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'If not using stall detection, the pose threshold to the docking '\n", + " 'pose whereisDocked()=true.',\n", + " 'filename': 'isDocked()=true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Tree XML Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Plugins\n", + "\n", + "\n", + "## Condition Plugins\n", + "\n", + "\n", + "## Control Plugins\n", + "\n", + "\n", + "## Decorator Plugins\n", + "\n", + "\n", + "## Example\n", + "This Behavior Tree replans the global path periodically at 1 Hz and it also has\n", + "recovery actions.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This Behavior Tree replans the global path periodically at 1 Hz '\n", + " 'and it also has\\n'\n", + " 'recovery actions.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: WouldAPlannerRecoveryHelp\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Port\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The active error code to compare against. This should match the '\n", + " 'planner server error code.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: BackUp\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Backup error code. SeeBackUpaction message for the enumerated '\n", + " 'set of error codes.',\n", + " 'filename': 'BackUp',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Planner Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When theplanner_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_navfn_planner::NavfnPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': '“nav2_navfn_planner::NavfnPlanner”',\n", + " 'filename': 'planner_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: RemoveInCollisionGoals\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'A vector of goals containing only those that are not in '\n", + " 'collision.',\n", + " 'filename': 'use_footprint=false',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "Note:dock_pluginsand eitherdocksordock_databaseare required.\n", + "\n", + "## SimpleChargingDock Parameters\n", + "Simple Charging Dock is a provided charging dock plugin that can handle many docks and common techniques.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " \"# Also 'opennav_docking::SimpleNonChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'id\\n'\n", + " ':\\n'\n", + " \"'c67f50cb-e152-4720-85cc-5eb20bd85ce8'\\n\"\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'If not using stall detection, the pose threshold to the docking '\n", + " 'pose whereisDocked()=true.',\n", + " 'filename': 'isDocked()=true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: UndockRobot\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Dock robot error code. SeeUndockRobotaction message for the '\n", + " 'enumerated set of error codes.',\n", + " 'filename': 'UndockRobot',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Waypoint Follower\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugin\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': '“nav2_waypoint_follower::WaitAtWaypoint”',\n", + " 'filename': 'nav2_waypoint_follower',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use.\n", + "Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package.\n", + "\n", + "## What is the Rotation Shim Controller?\n", + "This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers.\n", + "Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so.\n", + "Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task.\n", + "TheRotationShimControlleris most suitable for:\n", + "\n", + "## Configuring Rotation Shim Controller\n", + "This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through.\n", + "As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel.\n", + "The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted.\n", + "\n", + "## Configuring Primary Controller\n", + "There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity).\n", + "An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform.\n", + "\n", + "## Demo Execution\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'As such, its configuration looks very similar to that of any '\n", + " 'other plugin. In the code block below, you can see that we’ve '\n", + " 'added theRotationShimControlleras the plugin for path tracking '\n", + " 'in the controller server. You can see that we’ve also configured '\n", + " 'it below with its internal '\n", + " 'parameters,angular_dist_thresholdthroughmax_angular_accel.',\n", + " 'filename': 'max_angular_accel',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# DWB parameters\\n'\n", + " '...\\n'\n", + " '...\\n'\n", + " '...',\n", + " 'context': 'There is one more remaining parameter of '\n", + " 'theRotationShimControllernot mentioned above, '\n", + " 'theprimary_controller. This is the type of controller that your '\n", + " 'application would like to use as the primary modus operandi. It '\n", + " 'will share the same name and yaml namespace as the shim plugin. '\n", + " 'You can observe this below with the primary controller set '\n", + " 'theDWB(with the progress and goal checkers removed for brevity).',\n", + " 'filename': 'DWB',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ClearEntireCostmap\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Action server timeout (ms).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: CancelSpin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'spin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Waypoint Follower\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugin\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': '“nav2_waypoint_follower::WaitAtWaypoint”',\n", + " 'filename': 'nav2_waypoint_follower',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: AssistedTeleop\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Assisted teleop error code. SeeAssistedTeleopaction message for '\n", + " 'the enumerated set of error codes.',\n", + " 'filename': 'AssistedTeleop',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "Note:dock_pluginsand eitherdocksordock_databaseare required.\n", + "\n", + "## SimpleChargingDock Parameters\n", + "Simple Charging Dock is a provided charging dock plugin that can handle many docks and common techniques.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " \"# Also 'opennav_docking::SimpleNonChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'id\\n'\n", + " ':\\n'\n", + " \"'c67f50cb-e152-4720-85cc-5eb20bd85ce8'\\n\"\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'If not using stall detection, the pose threshold to the docking '\n", + " 'pose whereisDocked()=true.',\n", + " 'filename': 'isDocked()=true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Keepout Filter Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ']\\n'\n", + " '...\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '...\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ']\\n'\n", + " '...\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1',\n", + " 'context': 'Time with which to post-date the transform that is published, to '\n", + " 'indicate that this transform is valid into the future. Used when '\n", + " 'filter mask and current costmap layer are in different frames.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Detailed Behavior Tree Walkthrough\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document serves as a reference guide to the main behavior tree (BT) used in Nav2.\n", + "There are many example behavior trees provided innav2_bt_navigator/behavior_trees,\n", + "but these sometimes have to be re-configured based on the application of the robot.\n", + "The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail.\n", + "\n", + "## Prerequisites\n", + "\n", + "\n", + "## Navigate To Pose With Replanning and Recovery\n", + "The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml.\n", + "This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions.\n", + "BTs are primarily defined in XML. The tree shown above is represented in XML as follows.\n", + "This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time.\n", + "These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree.\n", + "This can be represented in the following way:\n", + "TheNavigationsubtree mainly involves actual navigation behavior:\n", + "TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally.\n", + "The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail\n", + "(path calculation or path following), contextual recoveries will be attempted.\n", + "If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE.\n", + "The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures.\n", + "This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6).\n", + "\n", + "## Navigation Subtree\n", + "Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree.\n", + "The XML of this subtree is as follows:\n", + "This subtree has two primary actionsComputePathToPoseandFollowPath.\n", + "If either of these two actions fail, they will attempt to clear the failure contextually.\n", + "The crux of the tree can be represented with only one parent and two children nodes like this:\n", + "The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked.\n", + "While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around.\n", + "Both theComputePathToPoseand theFollowPathfollow the same general structure.\n", + "The below is theComputePathToPosesubtree:\n", + "The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree.\n", + "The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap.\n", + "Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries.\n", + "The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below:\n", + "\n", + "## Recovery Subtree\n", + "TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree.\n", + "In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient).\n", + "And the XML snippet:\n", + "The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received.\n", + "If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries.\n", + "This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”.\n", + "These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree\n", + "in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge).\n", + "If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are:\n", + "UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree.\n", + "If this renavigation was not successful, the next child of theRoundRobinwill be ticked.\n", + "For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE:\n", + "(for the sake of this example, let’s assume that the goal is never updated).\n", + "If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure).\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'BTs are primarily defined in XML. The tree shown above is '\n", + " 'represented in XML as follows.',\n", + " 'filename': 'navigate_to_pose_w_replanning_and_recovery.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'This happens until thenumber_of_retriesfor the '\n", + " 'parentRecoveryNodeis exceeded (which by default is 6).',\n", + " 'filename': 'RecoveryNode',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The XML of this subtree is as follows:',\n", + " 'filename': 'Recovery',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'And the XML snippet:',\n", + " 'filename': 'Navigation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Kinematic Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Getting Involved\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Getting Involved\n", + "If you’re interested in getting involved in Navigation 2, first of all, welcome!\n", + "We encourage everyone to get involved from students, to junior developers, to senior developers, and executives.\n", + "There’s something to do for everyone from bug fixes, to feature development, new algorithms, and refactoring.\n", + "All ROS 2 TSC Working Groups have their meetings on theworking group calendar.\n", + "Here, you can find the date and time of the Navigation2 working group meeting. Make sure you’re checking in your local timezone.\n", + "From this calendar, you can add yourself to the event so it will appear on your google calendar and get the event link to the call through Google Hangouts.\n", + "We encourage everyone interested to come to the meeting to introduce yourself, your project, and see what everyone is working on.\n", + "Further,ROS Discourseis a good place to follow larger discussions happening in the community and announcements. This isnotthe correct place to post questions or ask for assistance. Please visitROS Answersfor Q&A.\n", + "Lastly, we have aCommunity Slackwhere we chat in real-time about topics in public channels or sidebar maintainers on individual projects via PMs. If you’re interested in contributing to Nav2, this is a great place to join!\n", + "If you’re looking to contribute code or bugs, please see the Process section below.\n", + "Over time, for developers that have an interest and have shown technical competence in an area of the stack, we elevate developers to a maintainers status.\n", + "That allows push rights to our protected branches, first-reviewers rights, and getting your name onAbout and Contact.\n", + "There currently is not a clear process for getting to be a maintainer, but if you’ve been involved and contributing over a duration of several months, you may be a good candidate and should email the project lead listed onAbout and Contact.\n", + "\n", + "## Process\n", + "After you’ve introduced yourself in a working group meeting (recommended, not required), you’re ready to get started!\n", + "We recommend a typical open-source project flow and value detail and transparency.\n", + "If you commit to something and need to pull back, say so.\n", + "We all know priorities change and appreciate the heads up so that task can go into the open queue of tasks.\n", + "The process is simple and is as follow:\n", + "Note: We take code quality seriously and strive for high-quality and consistent code.\n", + "We make use of the linting and static analysis tools provided in ROS 2 (ament_cpplint,ament_uncrustify,ament_cppcheck, etc).\n", + "All PRs are built in CI with the appropriate ROS distributions and run through a set of unit and system level tests including static analysis.\n", + "You can see the results of these tests in the pull request.\n", + "It is expected for feature development for tests to cover this work to be added.\n", + "If any documentation must be updated due to your changes, that should be included in your pull request.\n", + "\n", + "## Licensing\n", + "Licensing is very important to open source projects. It helps ensure the\n", + "software continues to be available under the terms that the author\n", + "desired.\n", + "Because much of the source code is ported from other ROS 1 projects, each\n", + "package has it’s own license. Contributions should be made under the predominant\n", + "license of that package. Entirely new packages should be made available under\n", + "theApache 2.0 license.\n", + "A license tells you what rights you have as a developer, as provided by\n", + "the copyright holder. It is important that the contributor fully\n", + "understands the licensing rights and agrees to them. Sometimes the\n", + "copyright holder isn’t the contributor, such as when the contributor is\n", + "doing work on behalf of a company.\n", + "If for some reason Apache 2.0 or BSD licenses are not appropriate for your work, please get in contact with a project maintainer and discuss your concerns or requirements.\n", + "We may consider special exceptions for exceptional work, within reason (we will not accept any licenses that makes it unsuitable for commercial use).\n", + "\n", + "## Developer Certification of Origin (DCO)\n", + "To make a good faith effort to ensure licensing criteria are met,\n", + "Nav2 encourages the Developer Certificate of Origin (DCO) process\n", + "to be followed.\n", + "The DCO is an attestation attached to every contribution made by a\n", + "developer. In the commit message of the contribution, (described more\n", + "fully later in this document), the developer simply adds aSigned-off-bystatement and thereby agrees to the DCO.\n", + "In practice, its easier to justgitcommit-s-m\"commitmessage.\".\n", + "Where-sadds this automatically.\n", + "If you forgot to add this to a commit, it is easy to append via:gitcommit--amend-s.\n", + "When a developer submits a patch, it is a commitment that the\n", + "contributor has the right to submit the patch per the license. The DCO\n", + "agreement is shown below and athttp://developercertificate.org/.\n", + "\n", + "Code Blocks:\n", + "[{'code': \"Developer's Certificate of Origin 1.1\\n\"\n", + " '\\n'\n", + " 'By making a contribution to this project, I certify that:\\n'\n", + " '\\n'\n", + " '(a) The contribution was created in whole or in part by me and I\\n'\n", + " ' have the right to submit it under the open source license\\n'\n", + " ' indicated in the file; or\\n'\n", + " '\\n'\n", + " '(b) The contribution is based upon previous work that, to the\\n'\n", + " ' best of my knowledge, is covered under an appropriate open\\n'\n", + " ' source license and I have the right under that license to\\n'\n", + " ' submit that work with modifications, whether created in whole\\n'\n", + " ' or in part by me, under the same open source license (unless\\n'\n", + " ' I am permitted to submit under a different license), as\\n'\n", + " ' Indicated in the file; or\\n'\n", + " '\\n'\n", + " '(c) The contribution was provided directly to me by some other\\n'\n", + " ' person who certified (a), (b) or (c) and I have not modified\\n'\n", + " ' it.\\n'\n", + " '\\n'\n", + " '(d) I understand and agree that this project and the contribution\\n'\n", + " ' are public and that a record of the contribution (including\\n'\n", + " ' all personal information I submit with it, including my\\n'\n", + " ' sign-off) is maintained indefinitely and may be redistributed\\n'\n", + " ' consistent with this project or the open source license(s)\\n'\n", + " ' involved.\\n',\n", + " 'context': 'When a developer submits a patch, it is a commitment that the\\n'\n", + " 'contributor has the right to submit the patch per the license. '\n", + " 'The DCO\\n'\n", + " 'agreement is shown below and athttp://developercertificate.org/.',\n", + " 'filename': 'gitcommit--amend-s',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: CancelControl\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'server_name',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Waypoint Follower\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugin\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': '“nav2_waypoint_follower::WaitAtWaypoint”',\n", + " 'filename': 'nav2_waypoint_follower',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dashing to Eloquent\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Packages\n", + "Navigation2 now includes a new packagenav2_waypoint_follower.\n", + "The waypoint follower is an action server that will take in a list of waypoints to follow and follow them in order.\n", + "There is a parameterstop_on_failurewhether the robot should continue to the next waypoint on a single waypoint failure,\n", + "or to return fail to the action client.\n", + "The waypoint follower is also a reference application for how to use the Navigation2 action server to complete a basic autonomy task.\n", + "Navigation2 now supports new algorithms for control and SLAM.\n", + "The Timed-Elastic Band (TEB) controller was implementedand can be found here.\n", + "It is its own controller plugin that can be used instead of the DWB controller.\n", + "Nav2 also supports SLAM Toolbox as the default SLAM implementation for ROS 2.\n", + "This replaces the use of Cartographer.\n", + "\n", + "## New Plugins\n", + "Eloquent introduces back in pluginlib plugins to the navigation stack.nav2_coredefines the plugin header interfaces to be used to implement controller, planner, recovery, and goal checker plugins.\n", + "All algorithms (NavFn, DWB, recoveries) were added as plugin interfaces and the general packages for servers were created.nav2_planneris the action server for planning that hosts a plugin for the planner.nav2_controlleris the action server for controller that hosts a plugin for the controller.nav2_recoveryis the action server for recovery that hosts a plugin for recovery.\n", + "New recovery plugins were added including backup, which will take in a distance to back up, if collision-free.\n", + "Additionally, the wait recovery was added that will wait a configurable period of time before trying to navigate again.\n", + "This plugin is especially helpful for time-dependent obstacles or pausing navigation for a scene to become less dynamic.\n", + "Many new behavior tree nodes were added. These behavior tree nodes are hard-coded in the behavior tree engine.\n", + "Behavior tree cpp v3 supports plugins and will be converted in the next release.\n", + "\n", + "## Navigation2 Architectural Changes\n", + "Thenav2_world_modelpackage was removed. The individualnav2_plannerandnav2_controllerservers now host their relevant costmaps.\n", + "This was done to reduce network traffic and ensure up-to-date information for the safety-critical elements of the system.\n", + "As above mentions, plugins were introduced into the stack and these servers each host plugins for navigation, control, and costmap layers.\n", + "Map server was substantially refactored but the external API remains the same. It now uses the SDL library for image loading.\n", + "TF-based positioning is now used for pose-estimation everywhere in the stack.\n", + "Prior, some elements of the navigation stack only updated its pose from the/amcl_posetopic publishing at an irregular rate.\n", + "This is obviously low-accuracy and high-latency.\n", + "All positioning is now based on the TF tree from the global frame to the robot frame.\n", + "Prior to Eloquent, there were no ROS 2 action servers and clients available.\n", + "Navigation2, rather, used an interface we called Tasks.\n", + "Eloquent now contains actions and a simple action server interface was created and is used now throughout the stack.\n", + "Tasks were removed.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: General Tutorials\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smac Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Description\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. It uses template node types to develop different search-based planners.\n", + "We support circular differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support car-like (ackermann) and legged vehicles using theSmacPlannerHybridplugin which implements a Hybrid-A* planner. We support non-circular, arbitrary shaped, any model vehicles using theSmacPlannerLatticeplugin which implements a State Lattice planner (e.g. omni, diff, ackermann, legged, custom). It contains control sets and generators for ackermann, legged, differential drive and omnidirectional vehicles, but you may provide your own for another robot type or to have different planning behaviors.\n", + "The last two plugins are bothkinematically feasibleand supportreversing. They have performance similar to its 2D counter parts like 2D-A* and NavFn via highly optimized heuristic functions and efficient programming. An example of the 3 planners can be seen below, planning a roughly 75 m path.\n", + "Usual planning times are below 100ms for some environments, occasionally approaching up to 200ms. The performance of all 3 planners is roughly comparable with naive 2D search algorithms that have long been mainstays of the ROS Navigation ecosystem, but also achieving kinematic feasibility, support for reversing, and using modern state of the art techniques.\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PreferForwardCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": PreferForwardCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: AMCL\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'amcl\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'alpha1\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha2\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha3\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha4\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha5\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'beam_skip_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'beam_skip_error_threshold\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'beam_skip_threshold\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'do_beamskip\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'global_frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'lambda_short\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'laser_likelihood_max_dist\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'laser_max_range\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'laser_min_range\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'laser_model_type\\n'\n", + " ':\\n'\n", + " '\"likelihood_field\"\\n'\n", + " 'max_beams\\n'\n", + " ':\\n'\n", + " '60\\n'\n", + " 'max_particles\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'min_particles\\n'\n", + " ':\\n'\n", + " '500\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'pf_err\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'pf_z\\n'\n", + " ':\\n'\n", + " '0.99\\n'\n", + " 'recovery_alpha_fast\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'recovery_alpha_slow\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'resample_interval\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'robot_model_type\\n'\n", + " ':\\n'\n", + " '\"nav2_amcl::DifferentialMotionModel\"\\n'\n", + " 'save_pose_rate\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'sigma_hit\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'tf_broadcast\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'update_min_a\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'update_min_d\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'z_hit\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'z_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_rand\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'z_short\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'scan_topic\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'set_initial_pose\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'always_reset_initial_pose\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'first_map_only\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'initial_pose\\n'\n", + " ':\\n'\n", + " 'x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'first_map_only_',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PhotoAtWaypoint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_waypoint_follower plugin name defined in thewaypoint_task_executor_plugin_idparameter inWaypoint Follower.\n", + "\n", + "=== Document ===\n", + "Title: Using VIO to Augment Robot Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry.\n", + "Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether.\n", + "A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements.\n", + "Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks.\n", + "Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module.\n", + "\n", + "## Setting Up the ZED X Camera\n", + "We’re using the ZED X for the purposes of this tutorial due to its:\n", + "Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed.\n", + "At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization.\n", + "As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree.\n", + "We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can!\n", + "\n", + "## Setting Up ZED ROS\n", + "In order to run VIO alone, we need to do the following:\n", + "Thus, make the following parameter updates to thezed_wrapper’s default parameters:\n", + "Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file:\n", + "\n", + "## Fusing VIO Into Local State Estimate\n", + "Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage.\n", + "This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation.\n", + "Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml.\n", + "Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only.\n", + "\n", + "## Fusing VSLAM Into Global State Estimate\n", + "While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except:\n", + "\n", + "## Testing it Out!\n", + "In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance.\n", + "The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level!\n", + "\n", + "Code Blocks:\n", + "[{'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedx.launch.py\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'zed_wrapper\\n'\n", + " 'zedxm.launch.py\\n',\n", + " 'context': 'At this point, you should be able to run one of the following '\n", + " 'commands to launch the driver and visualize the sensor data in '\n", + " 'Rviz. Note that these are ROS 2 component nodes that also may be '\n", + " 'loaded into your system’s component manager to minimize latency '\n", + " 'due to serialization.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'pos_tracking\\n'\n", + " ':\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables odom -> base_link TF transformation\\n'\n", + " 'publish_map_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Disables map -> odom TF transformation\\n'\n", + " 'area_memory\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Disables loop closure computation, but Pose topic for global '\n", + " 'VSLAM still published (but now pure VIO)\\n'\n", + " '# Optional optimizations\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Or true, up to you!\\n'\n", + " 'pos_tracking_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# of course!\\n'\n", + " 'path_max_count\\n'\n", + " ':\\n'\n", + " '30\\n'\n", + " 'qos_depth\\n'\n", + " ':\\n'\n", + " '5',\n", + " 'context': 'Thus, make the following parameter updates to thezed_wrapper’s '\n", + " 'default parameters:',\n", + " 'filename': 'zed_wrapper',\n", + " 'language': 'unknown'},\n", + " {'code': \"remappings\\n=\\n[(\\n'odom'\\n,\\n'camera_odom'\\n)]\",\n", + " 'context': 'Optionally, remap the zedodomtopic to a topic that isn’t '\n", + " 'reserved or commonly used by other systems. In your ZED launch '\n", + " 'file add to the node / launch file:',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom1\\n'\n", + " ':\\n'\n", + " 'camera_odom\\n'\n", + " '# Adjust if namespacing ZED camera (e.g. /zed/odom)\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# X, Y, Z\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " '# Roll, Pitch, Yaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vx, Vy, Vz\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " '# Vroll, Vpitch, Vyaw\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " '# Ax, Ay, Az\\n'\n", + " 'odom1_differential\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'odom1_relative\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'odom1_queue_size\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Most users at this point already have '\n", + " 'arobot_localizationconfiguration file in their robot systems to '\n", + " 'fuse existing sensors together, such as wheel odometry (even '\n", + " 'poor) and robot IMUs. We’ll be adding a new odom field,odom1, to '\n", + " 'our configuration to fuse in VIO’s position and orientation into '\n", + " 'our filter. If this is your first odometry field, useodom0and '\n", + " 'you can base your file onekf.yaml.',\n", + " 'filename': 'odom0',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: CancelDriveOnHeading\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'drive_on_heading',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Detailed Behavior Tree Walkthrough\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document serves as a reference guide to the main behavior tree (BT) used in Nav2.\n", + "There are many example behavior trees provided innav2_bt_navigator/behavior_trees,\n", + "but these sometimes have to be re-configured based on the application of the robot.\n", + "The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail.\n", + "\n", + "## Prerequisites\n", + "\n", + "\n", + "## Navigate To Pose With Replanning and Recovery\n", + "The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml.\n", + "This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions.\n", + "BTs are primarily defined in XML. The tree shown above is represented in XML as follows.\n", + "This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time.\n", + "These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree.\n", + "This can be represented in the following way:\n", + "TheNavigationsubtree mainly involves actual navigation behavior:\n", + "TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally.\n", + "The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail\n", + "(path calculation or path following), contextual recoveries will be attempted.\n", + "If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE.\n", + "The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures.\n", + "This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6).\n", + "\n", + "## Navigation Subtree\n", + "Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree.\n", + "The XML of this subtree is as follows:\n", + "This subtree has two primary actionsComputePathToPoseandFollowPath.\n", + "If either of these two actions fail, they will attempt to clear the failure contextually.\n", + "The crux of the tree can be represented with only one parent and two children nodes like this:\n", + "The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked.\n", + "While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around.\n", + "Both theComputePathToPoseand theFollowPathfollow the same general structure.\n", + "The below is theComputePathToPosesubtree:\n", + "The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree.\n", + "The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap.\n", + "Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries.\n", + "The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below:\n", + "\n", + "## Recovery Subtree\n", + "TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree.\n", + "In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient).\n", + "And the XML snippet:\n", + "The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received.\n", + "If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries.\n", + "This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”.\n", + "These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree\n", + "in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge).\n", + "If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are:\n", + "UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree.\n", + "If this renavigation was not successful, the next child of theRoundRobinwill be ticked.\n", + "For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE:\n", + "(for the sake of this example, let’s assume that the goal is never updated).\n", + "If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure).\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'BTs are primarily defined in XML. The tree shown above is '\n", + " 'represented in XML as follows.',\n", + " 'filename': 'navigate_to_pose_w_replanning_and_recovery.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'This happens until thenumber_of_retriesfor the '\n", + " 'parentRecoveryNodeis exceeded (which by default is 6).',\n", + " 'filename': 'RecoveryNode',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The XML of this subtree is as follows:',\n", + " 'filename': 'Recovery',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'And the XML snippet:',\n", + " 'filename': 'Navigation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Simple Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'max_its\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " 'w_data\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '0.3',\n", + " 'context': 'Weight to apply to smooth the path (smooths it)',\n", + " 'filename': '>=1',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Planner and Controller Servers\n", + "Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice.\n", + "The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment.\n", + "The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station.\n", + "As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server.\n", + "\n", + "## Selecting the Algorithm Plugins\n", + "In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server.\n", + "\n", + "## Planner Server\n", + "The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility.\n", + "As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments.\n", + "One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots.\n", + "Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds.\n", + "There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration.\n", + "\n", + "## Summary\n", + "\n", + "\n", + "## Example Configuration\n", + "An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Controller Server\n", + "The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity.\n", + "TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint.\n", + "Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots.\n", + "Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots.\n", + "The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots.\n", + "\n", + "## Summary\n", + "All of these algorithms work for both circular and non-circular robots.\n", + "\n", + "## Example Configuration\n", + "Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Non-circular Differential, Non-circular Omnidirectional',\n", + " 'filename': 'SmacLatticeplanner',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'All of these algorithms work for both circular and non-circular '\n", + " 'robots.',\n", + " 'filename': 'TrajectoryGenerationplugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GetPoseFromPath\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Pose from path, with the Path’s set header.',\n", + " 'filename': '-2',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Savitzky-Golay Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Savitzky-Golay Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"savitzky_golay_smoother\"\\n'\n", + " ']\\n'\n", + " 'savitzky_golay_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SavitzkyGolaySmoother\"\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Number of times to recursively smooth a segment',\n", + " 'filename': 'refinement_num',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dynamic Object Following\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely.\n", + "This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application:\n", + "The requirements for this task are as follows:\n", + "The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest,\n", + "send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Create the Behavior Tree\n", + "Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow:\n", + "First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node.\n", + "We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received.\n", + "To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance.\n", + "Now, you may save this behavior tree and use it in our navigation task.\n", + "For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage.\n", + "\n", + "## 1- Setup Rviz clicked point\n", + "We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to\n", + "publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone\n", + "this repo in your workspace, build, and type in a terminal.\n", + "ros2runnav2_test_utilsclicked_point_to_pose\n", + "Optionally, you can remap this topic in your rviz configuration file togoal_updates.\n", + "\n", + "## 2- Run Dynamic Object Following in Nav2 Simulation\n", + "Start Nav2 in one terminal:\n", + "ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml\n", + "Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial.\n", + "When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest!\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Let’s start from this simple behavior tree. This behavior tree '\n", + " 'replans a new path at 1 hz and passes that path to the '\n", + " 'controller to follow:',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'First, let’s make this behavior run until there’s a failure. For '\n", + " 'this purpose, we will use theKeepRunningUntilFailurecontrol '\n", + " 'node.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'We will then use the decoratorGoalUpdaterto accept updates of '\n", + " 'the dynamic object pose we’re trying to follow. This node takes '\n", + " 'as input the current goal and subscribes to the '\n", + " 'topic/goal_update. It sets the new goal asupdated_goalif a new '\n", + " 'goal on that topic is received.',\n", + " 'filename': 'updated_goal',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To stay at a certain distance from the target, we will use the '\n", + " 'action nodeTruncatePath. This node modifies a path making it '\n", + " 'shorter so we don’t try to navigate into the object of interest. '\n", + " 'We can set up the desired distance to the goal using the input '\n", + " 'portdistance.',\n", + " 'filename': 'distance',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Lifecycle Manager\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_manager\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'node_names\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " 'bond_timeout\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'attempt_respawn_reconnection\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'bond_respawn_max_duration\\n'\n", + " ':\\n'\n", + " '10.0',\n", + " 'context': 'When a server crashes or becomes non-responsive, the lifecycle '\n", + " 'manager will bring down all nodes for safety. This is the '\n", + " 'duration of which the lifecycle manager will attempt to '\n", + " 'reconnect with the failed server(s) during to recover and '\n", + " 're-activate the system. If this passes, it will stop attempts '\n", + " 'and will require a manual re-activation once the problem is '\n", + " 'manually resolved. Units: seconds.',\n", + " 'filename': 'true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Loopback Simulator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'loopback_simulator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'map_frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'scan_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_scan\"\\n'\n", + " \"# tb4_loopback_simulator.launch.py remaps to 'rplidar_link'\\n\"\n", + " 'update_duration\\n'\n", + " ':\\n'\n", + " '0.02',\n", + " 'context': 'Whether or not to publish simulated clock to/clock',\n", + " 'filename': '/clock',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Camera Calibration\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to obtain calibration parameters for monocular camera.\n", + "\n", + "## Requirements\n", + "1- Install Camera Calibration Parser, Camera Info Manager and Launch Testing Ament Cmake using operating system’s package manager:\n", + "2- Image Pipeline need to be built from source in your workspace with:\n", + "Also, make sure you have the following:\n", + "\n", + "## Tutorial Steps\n", + "1- Start a terminal in your GUI\n", + "2- Launch the ROS driver for your specific camera.\n", + "3- Make sure camera is publishing images over ROS. This can be tested by running:\n", + "4- This will show you all the topics published make sure that there is an image_raw topic /camera/image_raw. To confirm that its a real topic and actually publishing check topic hz:\n", + "5- Start the camera calibration node\n", + "6- In order to get a good calibration you will need to move the checkerboard around in the camera frame such that:\n", + "7- As the checkerboard is moved around the 4 bars on the calibration sidebar increases in length. When all then the 4 bars are green and enough data is available for calibration the CALIBRATE button will light up. Click it to see the results. It takes around the minute for calibration to take place.\n", + "8- After the calibration is completed the save and commit buttons light up. And you can also see the result in terminal.\n", + "9-Press the save button to see the result. Data is saved to “/tmp/calibrationdata.tar.gz”\n", + "11-In the folder images used for calibration are available and also “ost.yaml” and “ost.txt”. You can use the yaml file which contains the calibration parameters as directed by the camera driver.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Camera\\n'\n", + " 'Name\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'c\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'camera_name\\n'\n", + " 'name\\n'\n", + " 'of\\n'\n", + " 'the\\n'\n", + " 'camera\\n'\n", + " 'to\\n'\n", + " 'appear\\n'\n", + " 'in\\n'\n", + " 'the\\n'\n", + " 'calibration\\n'\n", + " 'file\\n'\n", + " 'Chessboard\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " 'You\\n'\n", + " 'must\\n'\n", + " 'specify\\n'\n", + " 'one\\n'\n", + " 'or\\n'\n", + " 'more\\n'\n", + " 'chessboards\\n'\n", + " 'as\\n'\n", + " 'pairs\\n'\n", + " 'of\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " 'and\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " 'options\\n'\n", + " '.\\n'\n", + " '-\\n'\n", + " 'p\\n'\n", + " 'PATTERN\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'pattern\\n'\n", + " '=\\n'\n", + " 'PATTERN\\n'\n", + " 'calibration\\n'\n", + " 'pattern\\n'\n", + " 'to\\n'\n", + " 'detect\\n'\n", + " '-\\n'\n", + " \"'chessboard'\\n\"\n", + " ',\\n'\n", + " \"'circles'\\n\"\n", + " ',\\n'\n", + " \"'acircles'\\n\"\n", + " ',\\n'\n", + " \"'charuco'\\n\"\n", + " '-\\n'\n", + " 's\\n'\n", + " 'SIZE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " '=\\n'\n", + " 'SIZE\\n'\n", + " 'chessboard\\n'\n", + " 'size\\n'\n", + " 'as\\n'\n", + " 'NxM\\n'\n", + " ',\\n'\n", + " 'counting\\n'\n", + " 'interior\\n'\n", + " 'corners\\n'\n", + " '(\\n'\n", + " 'e\\n'\n", + " '.\\n'\n", + " 'g\\n'\n", + " '.\\n'\n", + " 'a\\n'\n", + " 'standard\\n'\n", + " 'chessboard\\n'\n", + " 'is\\n'\n", + " '7\\n'\n", + " 'x7\\n'\n", + " ')\\n'\n", + " '-\\n'\n", + " 'q\\n'\n", + " 'SQUARE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " '=\\n'\n", + " 'SQUARE\\n'\n", + " 'chessboard\\n'\n", + " 'square\\n'\n", + " 'size\\n'\n", + " 'in\\n'\n", + " 'meters\\n'\n", + " 'ROS\\n'\n", + " 'Communication\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'approximate\\n'\n", + " '=\\n'\n", + " 'APPROXIMATE\\n'\n", + " 'allow\\n'\n", + " 'specified\\n'\n", + " 'slop\\n'\n", + " '(\\n'\n", + " 'in\\n'\n", + " 'seconds\\n'\n", + " ')\\n'\n", + " 'when\\n'\n", + " 'pairing\\n'\n", + " 'images\\n'\n", + " 'from\\n'\n", + " 'unsynchronized\\n'\n", + " 'stereo\\n'\n", + " 'cameras\\n'\n", + " '--\\n'\n", + " 'no\\n'\n", + " '-\\n'\n", + " 'service\\n'\n", + " '-\\n'\n", + " 'check\\n'\n", + " 'disable\\n'\n", + " 'check\\n'\n", + " 'for\\n'\n", + " 'set_camera_info\\n'\n", + " 'services\\n'\n", + " 'at\\n'\n", + " 'startup\\n'\n", + " 'Calibration\\n'\n", + " 'Optimizer\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'principal\\n'\n", + " '-\\n'\n", + " 'point\\n'\n", + " 'fix\\n'\n", + " 'the\\n'\n", + " 'principal\\n'\n", + " 'point\\n'\n", + " 'at\\n'\n", + " 'the\\n'\n", + " 'image\\n'\n", + " 'center\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'aspect\\n'\n", + " '-\\n'\n", + " 'ratio\\n'\n", + " 'enforce\\n'\n", + " 'focal\\n'\n", + " 'lengths\\n'\n", + " '(\\n'\n", + " 'fx\\n'\n", + " ',\\n'\n", + " 'fy\\n'\n", + " ')\\n'\n", + " 'are\\n'\n", + " 'equal\\n'\n", + " '--\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'tangent\\n'\n", + " '-\\n'\n", + " 'dist\\n'\n", + " 'set\\n'\n", + " 'tangential\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " '(\\n'\n", + " 'p1\\n'\n", + " ',\\n'\n", + " 'p2\\n'\n", + " ')\\n'\n", + " 'to\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'k\\n'\n", + " 'NUM_COEFFS\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'k\\n'\n", + " '-\\n'\n", + " 'coefficients\\n'\n", + " '=\\n'\n", + " 'NUM_COEFFS\\n'\n", + " 'number\\n'\n", + " 'of\\n'\n", + " 'radial\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " 'to\\n'\n", + " 'use\\n'\n", + " '(\\n'\n", + " 'up\\n'\n", + " 'to\\n'\n", + " '6\\n'\n", + " ',\\n'\n", + " 'default\\n'\n", + " '2\\n'\n", + " ')\\n'\n", + " '--\\n'\n", + " 'disable_calib_cb_fast_check\\n'\n", + " 'uses\\n'\n", + " 'the\\n'\n", + " 'CALIB_CB_FAST_CHECK\\n'\n", + " 'flag\\n'\n", + " 'for\\n'\n", + " 'findChessboardCorners\\n'\n", + " 'This\\n'\n", + " 'will\\n'\n", + " 'open\\n'\n", + " 'a\\n'\n", + " 'calibration\\n'\n", + " 'window\\n'\n", + " 'which\\n'\n", + " 'highlight\\n'\n", + " 'the\\n'\n", + " 'checkerboard\\n'\n", + " '.',\n", + " 'context': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'filename': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Groot - Interacting with Behavior Trees\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Grootis the companion application of theBehaviorTree.CPPlibrary used to create, edit, and visualize behavior trees.\n", + "Behavior Trees are deeply integrated into Nav2, used as the main method of orchestrating task server logic across a complex navigation and autonomy stack.\n", + "Behavior Trees, in short BTs, consist of many nodes completing different tasks and control the flow of logic, similar to a Hierarchical or Finite State Machine, but organized in a tree structure.\n", + "These nodes are of types:Action,Condition,Control, orDecorator, and are described in more detail inNavigation ConceptsandBehaviorTree.CPP.\n", + "Writing a New Behavior Tree Pluginoffers a well written example of creating a simpleActionnode if creating new BT nodes is of interest. This tutorial will focus solely on launching Groot, visualizing a Behavior Tree, and modifying that tree for a given customization, assuming a library of BT nodes. Luckily, Nav2 provides a robust number of BT nodes for your use out of the box, enumerated inNavigation Plugins.\n", + "A BT configuration file in BehaviorTree.CPP is an XML file. This is used to dynamically load the BT node plugins at run-time from the appropriate libraries mapped to their names. The XML format is definedin detail here. Therefore, Groot needs to have a list of nodes it has access to and important metadata about them like their type and ports (or parameters). We refer to this as the “palette” of nodes later in the tutorial.\n", + "In the video above you can see Groot side-by-side with RVIz and a test platform 100% equipped with ROS-enabled hardware from SIEMENS.\n", + "Groot not only displays the current Behavior Tree while the robot is operating. Note: Before ROS 2 Humble, live Groot behavior tree monitoring during execution was supported in Nav2. This was removed due to buggy support in BT.CPP / Groot for changing behavior trees on the fly, seeGalactic to Humblefor more details.\n", + "\n", + "## Visualize Behavior Trees\n", + "To display a Behavior Tree like that inFigure 3, we will first start the Groot executable.\n", + "Out of the box, Groot can only display Behavior Trees and nodes that are from the defaults in BT.CPP, since it does not know anything about Nav2 or your other projects.\n", + "Therefore, we must point Groot to our palette, or index, of Nav2 / custom behavior tree nodes:\n", + "If you select the default treenavigate_w_replanning_and_recovery.xml, then a Groot editor should look likeFigure 3.\n", + "\n", + "## Edit Behavior Trees\n", + "Now that you have a Nav2 BT open in Groot in editor mode, you should be able to trivially modify it using the GUI.\n", + "Starting from a screen like that shown inFigure 3, you can pull in new nodes from the side panel to add them to the workspace.\n", + "You may then connect the nodes using a “drag and drop” motion between the node’s input and output ports to assemble the new nodes into the tree.\n", + "If you select a given node, you can change metadata about it such as its name or values of parameterizable ports. When you’re done modifying, simply save the new configuration file and use that on your robot the next time!\n", + "\n", + "## Adding A Custom Node\n", + "Each node in the behavior tree holds a specialized function.\n", + "Sometimes, its useful to create new nodes and add them to your palette during the design process - perhaps before the implementations themselves exist.\n", + "This helps designers abstract away the implementation specifics of the nodes from the higher level logic of the tree itself and how they’d like to interact with a given node (e.g. type, ports, etc).\n", + "Within Groot, you may create new custom nodes to add to your tree and export these new nodes back to your palette.\n", + "Implementing the node itself needs to be done separately from Groot, which is described inWriting a New Behavior Tree Plugin.\n", + "Creating a new custom node can be started by clicking the orange marked icon inFigure 4, while Groot is in Editor mode.\n", + "This should load a new window, similar toFigure 5.\n", + "In this new window, it asks you to fill in the metadata about this new node, in order to create it.\n", + "It will ask you for standard information such as name (green box), type of node (orange box), and any optional ports for parameterization or access to blackboard variables (blue box).\n", + "After completing, selectOKinFigure 5, the new custom node should appear in blue in theTreeNode Paletteas inFigure 6.\n", + "Before starting to create a new BT based on the new custom nodes, it is recommend to export the newly created nodes to save in case of Groot crashing.\n", + "This can be performed with the icon highlighted in green fromFigure 6.\n", + "The resulting XML output from the node created inFigure 5can be seen below.\n", + "You can see more examples inNav2’s BT Node Palette XML.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'coffee\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Sense\\n'\n", + " 'of\\n'\n", + " 'life\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rolling\\n'\n", + " 'target\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Before starting to create a new BT based on the new custom '\n", + " 'nodes, it is recommend to export the newly created nodes to save '\n", + " 'in case of Groot crashing.\\n'\n", + " 'This can be performed with the icon highlighted in green '\n", + " 'fromFigure 6.\\n'\n", + " 'The resulting XML output from the node created inFigure 5can be '\n", + " 'seen below.\\n'\n", + " 'You can see more examples inNav2’s BT Node Palette XML.',\n", + " 'filename': 'Action',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up the Robot’s Footprint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Footprint Introduction\n", + "The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans.\n", + "The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used.\n", + "For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization.\n", + "For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot.\n", + "Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Configuring the Robot’s Footprint\n", + "In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps.\n", + "Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot.\n", + "Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot.\n", + "For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We will now confirm that we have properly set upsam_bot’s footprint.\n", + "First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below.\n", + "After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor.\n", + "Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below.\n", + "Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors.\n", + "Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following:\n", + "We should now be able to visualize the footprints in RViz, which will be discussed in the next section.\n", + "\n", + "## Visualizing Footprint in RViz\n", + "To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot:\n", + "On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot:\n", + "\n", + "## Conclusion\n", + "In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function.\n", + "As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '188\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '189\\n'\n", + " 'footprint\\n'\n", + " ':\\n'\n", + " '\"[\\n'\n", + " '[0.21,\\n'\n", + " '0.195],\\n'\n", + " '[0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '0.195]\\n'\n", + " ']\"\\n'\n", + " '190\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Below is the code snippet fromnav2_params.yamldefining the local '\n", + " 'costmap footprint. In this configuration file, '\n", + " 'thefootprintparameter of the local costmap has already been set '\n", + " 'with a rectangular-shaped footprint. This box is centered at '\n", + " 'thebase_linkframe ofsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '232\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '233\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " '234\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': 'For the global costmap, we have already set '\n", + " 'therobot_radiusparameter to create a circular footprint that '\n", + " 'matchessam_bot’s size and centered atbase_link. The parameter '\n", + " 'that was modified is shown in the code snippet below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'First, we launchlaunch/display.launch.pyto launch the robot '\n", + " 'state publisher, spawnsam_botin Gazebo, and visualizesam_botand '\n", + " 'its footprint in Rviz. The robot state publisher publishes '\n", + " 'thebase_link=>sensorstransforms defined insam_bot’s URDF, while '\n", + " 'Gazebo’s differential drive plugin publishes '\n", + " 'theodom=>base_linktransform. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'map\\n'\n", + " 'odom\\n',\n", + " 'context': 'Next, we will publish themap=>odomtransform using '\n", + " 'thestatic_transform_publisher. We publish themap=>odomtransform '\n", + " 'as static in this guide as a simple way to publish the transform '\n", + " 'and visualize the footprint. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'navigation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '\\n',\n", + " 'context': 'Lastly, we will launch Nav2 using '\n", + " 'thenav2_params.yamlconfiguration file we just made '\n", + " 'andnavigation_launch.py, the built-in launch file '\n", + " 'ofnav2_bringup. Open a new terminal and execute the following:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: CancelCoverage\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'server_name',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smoother Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Smoother Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Regulated Pure Pursuit\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Regulated Pure Pursuit Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController\"\\n'\n", + " 'desired_linear_vel\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'min_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'max_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'lookahead_time\\n'\n", + " ':\\n'\n", + " '1.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_velocity_scaled_lookahead_dist\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'min_approach_linear_velocity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'approach_velocity_scaling_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'use_collision_detection\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_allowed_time_to_collision_up_to_carrot\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'use_regulated_linear_velocity_scaling\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_fixed_curvature_lookahead\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'curvature_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'use_cost_regulated_linear_velocity_scaling\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'regulated_linear_scaling_min_radius\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'regulated_linear_scaling_min_speed\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'use_rotate_to_heading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'allow_reversing\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotate_to_heading_min_angle\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'max_robot_pose_search_dist\\n'\n", + " ':\\n'\n", + " '10.0',\n", + " 'context': 'Note: Needsuse_fixed_curvature_lookaheadto betrue',\n", + " 'filename': 'true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Lifecycle Manager\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_manager\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'node_names\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " 'bond_timeout\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'attempt_respawn_reconnection\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'bond_respawn_max_duration\\n'\n", + " ':\\n'\n", + " '10.0',\n", + " 'context': 'When a server crashes or becomes non-responsive, the lifecycle '\n", + " 'manager will bring down all nodes for safety. This is the '\n", + " 'duration of which the lifecycle manager will attempt to '\n", + " 'reconnect with the failed server(s) during to recover and '\n", + " 're-activate the system. If this passes, it will stop attempts '\n", + " 'and will require a manual re-activation once the problem is '\n", + " 'manually resolved. Units: seconds.',\n", + " 'filename': 'true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Camera Calibration\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to obtain calibration parameters for monocular camera.\n", + "\n", + "## Requirements\n", + "1- Install Camera Calibration Parser, Camera Info Manager and Launch Testing Ament Cmake using operating system’s package manager:\n", + "2- Image Pipeline need to be built from source in your workspace with:\n", + "Also, make sure you have the following:\n", + "\n", + "## Tutorial Steps\n", + "1- Start a terminal in your GUI\n", + "2- Launch the ROS driver for your specific camera.\n", + "3- Make sure camera is publishing images over ROS. This can be tested by running:\n", + "4- This will show you all the topics published make sure that there is an image_raw topic /camera/image_raw. To confirm that its a real topic and actually publishing check topic hz:\n", + "5- Start the camera calibration node\n", + "6- In order to get a good calibration you will need to move the checkerboard around in the camera frame such that:\n", + "7- As the checkerboard is moved around the 4 bars on the calibration sidebar increases in length. When all then the 4 bars are green and enough data is available for calibration the CALIBRATE button will light up. Click it to see the results. It takes around the minute for calibration to take place.\n", + "8- After the calibration is completed the save and commit buttons light up. And you can also see the result in terminal.\n", + "9-Press the save button to see the result. Data is saved to “/tmp/calibrationdata.tar.gz”\n", + "11-In the folder images used for calibration are available and also “ost.yaml” and “ost.txt”. You can use the yaml file which contains the calibration parameters as directed by the camera driver.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Camera\\n'\n", + " 'Name\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'c\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'camera_name\\n'\n", + " 'name\\n'\n", + " 'of\\n'\n", + " 'the\\n'\n", + " 'camera\\n'\n", + " 'to\\n'\n", + " 'appear\\n'\n", + " 'in\\n'\n", + " 'the\\n'\n", + " 'calibration\\n'\n", + " 'file\\n'\n", + " 'Chessboard\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " 'You\\n'\n", + " 'must\\n'\n", + " 'specify\\n'\n", + " 'one\\n'\n", + " 'or\\n'\n", + " 'more\\n'\n", + " 'chessboards\\n'\n", + " 'as\\n'\n", + " 'pairs\\n'\n", + " 'of\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " 'and\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " 'options\\n'\n", + " '.\\n'\n", + " '-\\n'\n", + " 'p\\n'\n", + " 'PATTERN\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'pattern\\n'\n", + " '=\\n'\n", + " 'PATTERN\\n'\n", + " 'calibration\\n'\n", + " 'pattern\\n'\n", + " 'to\\n'\n", + " 'detect\\n'\n", + " '-\\n'\n", + " \"'chessboard'\\n\"\n", + " ',\\n'\n", + " \"'circles'\\n\"\n", + " ',\\n'\n", + " \"'acircles'\\n\"\n", + " ',\\n'\n", + " \"'charuco'\\n\"\n", + " '-\\n'\n", + " 's\\n'\n", + " 'SIZE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " '=\\n'\n", + " 'SIZE\\n'\n", + " 'chessboard\\n'\n", + " 'size\\n'\n", + " 'as\\n'\n", + " 'NxM\\n'\n", + " ',\\n'\n", + " 'counting\\n'\n", + " 'interior\\n'\n", + " 'corners\\n'\n", + " '(\\n'\n", + " 'e\\n'\n", + " '.\\n'\n", + " 'g\\n'\n", + " '.\\n'\n", + " 'a\\n'\n", + " 'standard\\n'\n", + " 'chessboard\\n'\n", + " 'is\\n'\n", + " '7\\n'\n", + " 'x7\\n'\n", + " ')\\n'\n", + " '-\\n'\n", + " 'q\\n'\n", + " 'SQUARE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " '=\\n'\n", + " 'SQUARE\\n'\n", + " 'chessboard\\n'\n", + " 'square\\n'\n", + " 'size\\n'\n", + " 'in\\n'\n", + " 'meters\\n'\n", + " 'ROS\\n'\n", + " 'Communication\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'approximate\\n'\n", + " '=\\n'\n", + " 'APPROXIMATE\\n'\n", + " 'allow\\n'\n", + " 'specified\\n'\n", + " 'slop\\n'\n", + " '(\\n'\n", + " 'in\\n'\n", + " 'seconds\\n'\n", + " ')\\n'\n", + " 'when\\n'\n", + " 'pairing\\n'\n", + " 'images\\n'\n", + " 'from\\n'\n", + " 'unsynchronized\\n'\n", + " 'stereo\\n'\n", + " 'cameras\\n'\n", + " '--\\n'\n", + " 'no\\n'\n", + " '-\\n'\n", + " 'service\\n'\n", + " '-\\n'\n", + " 'check\\n'\n", + " 'disable\\n'\n", + " 'check\\n'\n", + " 'for\\n'\n", + " 'set_camera_info\\n'\n", + " 'services\\n'\n", + " 'at\\n'\n", + " 'startup\\n'\n", + " 'Calibration\\n'\n", + " 'Optimizer\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'principal\\n'\n", + " '-\\n'\n", + " 'point\\n'\n", + " 'fix\\n'\n", + " 'the\\n'\n", + " 'principal\\n'\n", + " 'point\\n'\n", + " 'at\\n'\n", + " 'the\\n'\n", + " 'image\\n'\n", + " 'center\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'aspect\\n'\n", + " '-\\n'\n", + " 'ratio\\n'\n", + " 'enforce\\n'\n", + " 'focal\\n'\n", + " 'lengths\\n'\n", + " '(\\n'\n", + " 'fx\\n'\n", + " ',\\n'\n", + " 'fy\\n'\n", + " ')\\n'\n", + " 'are\\n'\n", + " 'equal\\n'\n", + " '--\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'tangent\\n'\n", + " '-\\n'\n", + " 'dist\\n'\n", + " 'set\\n'\n", + " 'tangential\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " '(\\n'\n", + " 'p1\\n'\n", + " ',\\n'\n", + " 'p2\\n'\n", + " ')\\n'\n", + " 'to\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'k\\n'\n", + " 'NUM_COEFFS\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'k\\n'\n", + " '-\\n'\n", + " 'coefficients\\n'\n", + " '=\\n'\n", + " 'NUM_COEFFS\\n'\n", + " 'number\\n'\n", + " 'of\\n'\n", + " 'radial\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " 'to\\n'\n", + " 'use\\n'\n", + " '(\\n'\n", + " 'up\\n'\n", + " 'to\\n'\n", + " '6\\n'\n", + " ',\\n'\n", + " 'default\\n'\n", + " '2\\n'\n", + " ')\\n'\n", + " '--\\n'\n", + " 'disable_calib_cb_fast_check\\n'\n", + " 'uses\\n'\n", + " 'the\\n'\n", + " 'CALIB_CB_FAST_CHECK\\n'\n", + " 'flag\\n'\n", + " 'for\\n'\n", + " 'findChessboardCorners\\n'\n", + " 'This\\n'\n", + " 'will\\n'\n", + " 'open\\n'\n", + " 'a\\n'\n", + " 'calibration\\n'\n", + " 'window\\n'\n", + " 'which\\n'\n", + " 'highlight\\n'\n", + " 'the\\n'\n", + " 'checkerboard\\n'\n", + " '.',\n", + " 'context': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'filename': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DWB Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Controller\n", + "\n", + "\n", + "## Plugins\n", + "The plugins listed below are inside thedwb_pluginsnamespace.\n", + "\n", + "## Trajectory Critics\n", + "The trajectory critics listed below are inside thedwb_criticsnamespace.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# controller server parameters (see Controller Server for more '\n", + " 'info)\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# DWB controller parameters\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'debug_trajectory_details\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'min_vel_x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'min_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'max_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_theta\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_speed_xy\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_speed_xy\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'min_speed_theta\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_x\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'acc_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_theta\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'decel_lim_x\\n'\n", + " ':\\n'\n", + " '-2.5\\n'\n", + " 'decel_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'decel_lim_theta\\n'\n", + " ':\\n'\n", + " '-3.2\\n'\n", + " 'vx_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'vy_samples\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'vtheta_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'sim_time\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'linear_granularity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'angular_granularity\\n'\n", + " ':\\n'\n", + " '0.025\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'trans_stopped_velocity\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'short_circuit_trajectory_evaluation\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'limit_vel_cmd_in_traj\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"RotateToGoal\"\\n'\n", + " ',\\n'\n", + " '\"Oscillation\"\\n'\n", + " ',\\n'\n", + " '\"BaseObstacle\"\\n'\n", + " ',\\n'\n", + " '\"GoalAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathDist\"\\n'\n", + " ',\\n'\n", + " '\"GoalDist\"\\n'\n", + " ']\\n'\n", + " 'BaseObstacle.scale\\n'\n", + " ':\\n'\n", + " '0.02\\n'\n", + " 'PathAlign.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalAlign.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'PathAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'GoalAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'PathDist.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalDist.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'RotateToGoal.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'RotateToGoal.slowing_factor\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'RotateToGoal.lookahead_time\\n'\n", + " ':\\n'\n", + " '-1.0',\n", + " 'context': 'The trajectory critics listed below are inside '\n", + " 'thedwb_criticsnamespace.',\n", + " 'filename': 'dwb_critics',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: RoundRobin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n\\n',\n", + " 'context': 'Custom control flow node used to create a round-robin behavior '\n", + " 'for children BT nodes.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Map Server / Saver\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Map Saver Parameters\n", + "\n", + "\n", + "## Map Server Parameters\n", + "\n", + "\n", + "## Costmap Filter Info Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'map_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"turtlebot3_world.yaml\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'map_saver\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'save_map_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'free_thresh_default\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'occupied_thresh_default\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'filter_space_value=base+multiplier*mask_value',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Smac 2D Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smac_planner::SmacPlanner2D\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '0.125\\n'\n", + " '# tolerance for planning if unable to reach exact pose, in meters\\n'\n", + " 'downsample_costmap\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# whether or not to downsample the map\\n'\n", + " 'downsampling_factor\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " '# multiplier for the resolution of the costmap layer (e.g. 2 on a '\n", + " '5cm costmap would be 10cm)\\n'\n", + " 'allow_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# allow traveling in unknown space\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '1000000\\n'\n", + " '# maximum total iterations to search for before failing (in case '\n", + " 'unreachable), set to -1 to disable\\n'\n", + " 'max_on_approach_iterations\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " '# maximum number of iterations to attempt to reach goal once in '\n", + " 'tolerance\\n'\n", + " 'max_planning_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '# max time in s for planner to plan, smooth\\n'\n", + " 'cost_travel_multiplier\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '# Cost multiplier to apply to search to steer away from high cost '\n", + " 'areas. Larger values will place in the center of aisles more '\n", + " 'exactly (if non-`FREE` cost potential field exists) but take '\n", + " 'slightly longer to compute. To optimize for speed, a value of 1.0 '\n", + " 'is reasonable. A reasonable tradeoff value is 2.0. A value of 0.0 '\n", + " 'effective disables steering away from obstacles and acts like a '\n", + " 'naive binary search A*.\\n'\n", + " 'use_final_approach_orientation\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " \"# Whether to set the final path pose at the goal's orientation to \"\n", + " 'the requested orientation (false) or in line with the approach '\n", + " \"angle so the robot doesn't rotate to heading (true)\\n\"\n", + " 'smoother\\n'\n", + " ':\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'w_data\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10',\n", + " 'context': 'Parameter tolerance change amount to terminate smoothing session',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: PlannerSelector\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The output selected planner id. This selected_planner string is '\n", + " 'usually passed to the ComputePathToPose behavior via the '\n", + " 'planner_id input port.',\n", + " 'filename': 'transientlocal',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ComputeCoveragePath\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "Note: the blackboard IDs for the path, error code, and more may be adjusted,but need to match the corresponding parameters in theCoverageNavigatorplugin to set on the blackboard for use from the action server.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Compute coverage error code. SeeComputeCoveragePathaction '\n", + " 'message for the enumerated set of error codes.',\n", + " 'filename': 'ComputeCoveragePath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a New Nav2 Task Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Lifecycle Nodes\n", + "The Lifecycle node is the first key component of a nav2 task server. Lifecycle nodes were introduced in ROS 2 to systematically manage the bringup and shutdown of the different nodes involved in the robot’s operation. The use of Lifecycle nodes ensures that all nodes are successfully instantiated before they begin their execution and Nav2 shuts down all nodes if there is any unresponsive node.\n", + "Lifecycle nodes contain state machine transitions that enable deterministic behavior in ROS 2 servers. The Lifecycle node transitions in Nav2 are handled by theLifecycleManager. The Lifecycle Manager transitions the states of the Lifecycle nodes and provides greater control over the state of a system.\n", + "The primary states of a Lifecycle node areUnconfigured,Inactive,Active, andFinalized. A Lifecycle node starts in anUnconfiguredstate after being instantiated. The Lifecycle Manager transitions a node fromUnconfiguredtoInactiveby implementing theConfiguratingtransition. TheConfiguratingtransition sets up all configuration parameters and prepares any required setup such as memory allocation and the set up of the static publication and subscription topics. A node in theInactivestate is allowed to reconfigure its parameters and but cannot perform any processing. From theInactivestate, the Lifecycle Manager implements theActivatingtransition state to transition the node fromInactivetoActive, which is the main state. A node in theActivestate is allowed to perform any processing operation. In case a node crashes, the Lifecycle Manager shuts down the system to prevent any critical failures. On shutdown, the necessary cleanup operations are performed and the nodes are transitioned to theFinalizedstate viaDeactivating,CleaningUp, andShuttingDowntransition states.\n", + "You may wish to integrate your own nodes into the Nav2 framework or add new lifecycle nodes to your system. As an example, we will add a new notional lifecycle nodesensor_driver, and have it be controlled via the Nav2 Lifecycle Manager to ensure sensor feeds are available before activating navigation. You can do so by adding asensor_drivernode in your launch file and adding it to the list of nodes to be activated by thelifecycle_managerbefore navigation, as shown in the example below.\n", + "In the snippet above, the nodes to be handled by the Lifecycle Manager are set using thenode_namesparameter. Thenode_namesparameter takes in an ordered list of nodes to bringup through the Lifecycle transition. As shown in the snippet, thenode_namesparameter takes inlifecycle_nodeswhich contains the list of nodes to be added to the Lifecycle Manager. The Lifecycle Manager implements bringup transitions (ConfiguringandActivating) to the nodes one-by-one and in order, while the nodes are processed in reverse order for shutdown transitions. Hence, thesensor_driveris listed first before the other navigation servers so that the sensor data is available before the navigation servers are activated.\n", + "Two other parameters of the Lifecycle Manager areautostartandbond_timeout. Setautostarttotrueif you want to set the transition nodes to theActivestate on startup. Otherwise, you will need to manually trigger Lifecycle Manager to transition up the system. Thebond_timeoutsets the waiting time to decide when to transition down all of the nodes if a node is not responding.\n", + "\n", + "## Composition\n", + "Composition is the second key component nav2 task servers that was introduced to reduce the memory and CPU resources by putting multiple nodes in a single process. In Nav2, Composition can be used to compose all Nav2 nodes in a single process instead of launching them separately. This is useful for deployment on embedded systems where developers need to optimize resource usage.\n", + "In the following section, we give an example on how to add a new Nav2 server, which we notionally call theroute_server, to our system.\n", + "We make use of the launch files to compose different servers into a single process. The process is established by theComposableNodeContainercontainer that is populated with composition nodes viaComposableNode. This container can then be launched and used the same as any other Nav2 node.\n", + "\n", + "## Error codes\n", + "Your nav2 task server may also wish to return a ‘error_code’ in its action response (though not required). If there are semantically meaningful and actionable types of failures for your system, this is a systemic way to communicate those failures which may be automatically aggregated into the responses of the navigation system to your application.\n", + "It is important to note that error codes from 0-9999 are reserved for internal nav2 servers with each server offset by 100 while external servers start at 10000 and end at 65535.\n", + "The table below shows the current servers along with the expected error code structure.\n", + "Error codes are attached to the response of the action message. An example can be seen below for the route server. Note that by convention we set the error code field within the message definition toerror_code.\n", + "As stated in the message, the priority order of the errors should match the message order, 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "Since the the route server is a external server, the errors codes start at 10000 and go up to 10099.\n", + "In order to propagate your server’s error code to the rest of the system it must be added to the nav2_params.yaml file.\n", + "Theerror_code_id_namesinside of the BT Navigator define what error codes to look for on the blackboard by the server. The lowest error code of the sequence is then returned - whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "\n", + "## Conclusion\n", + "In this section of the guide, we have discussed Lifecycle Nodes, Composition and Error Codes which are new and important concepts in ROS 2. We also showed how to implement Lifecycle Nodes, Composition and Error Codes to your newly created nodes/servers with Nav2. These three concepts are helpful to efficiently run your system and therefore are encouraged to be used throughout Nav2.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'smoother_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " '...\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_navigation'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),',\n", + " 'context': 'You may wish to integrate your own nodes into the Nav2 framework '\n", + " 'or add new lifecycle nodes to your system. As an example, we '\n", + " 'will add a new notional lifecycle nodesensor_driver, and have it '\n", + " 'be controlled via the Nav2 Lifecycle Manager to ensure sensor '\n", + " 'feeds are available before activating navigation. You can do so '\n", + " 'by adding asensor_drivernode in your launch file and adding it '\n", + " 'to the list of nodes to be activated by '\n", + " 'thelifecycle_managerbefore navigation, as shown in the example '\n", + " 'below.',\n", + " 'filename': 'lifecycle_manager',\n", + " 'language': 'unknown'},\n", + " {'code': 'container\\n'\n", + " '=\\n'\n", + " 'ComposableNodeContainer\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'my_container'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rclcpp_components'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'component_container'\\n\"\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server::RouteServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " '),\\n'\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " ')',\n", + " 'context': 'Add a newComposableNode()instance in your launch file pointing '\n", + " 'to the component container of your choice.',\n", + " 'filename': 'ComposableNode()',\n", + " 'language': 'unknown'},\n", + " {'code': '\\nnav2_route_server\\n',\n", + " 'context': 'Add the package containing the server to yourpackage.xmlfile.',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '# Error codes\\n'\n", + " '# Note: The expected priority order of the errors should match the '\n", + " 'message order\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'NONE\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " '# 0 is reserved for NONE\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'UNKNOWN\\n'\n", + " '=\\n'\n", + " '10000\\n'\n", + " '# first error code in the sequence is reserved for UNKNOWN\\n'\n", + " '# User Error codes below\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'INVALID_START\\n'\n", + " '=\\n'\n", + " '10001\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'NO_VALID_ROUTE\\n'\n", + " '=\\n'\n", + " '10002\\n'\n", + " '#goal definition\\n'\n", + " '\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'goal\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'start\\n'\n", + " 'string\\n'\n", + " 'route_id\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'nav_msgs/Route\\n'\n", + " 'route\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'route_time\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '---\\n',\n", + " 'context': 'Error codes are attached to the response of the action message. '\n", + " 'An example can be seen below for the route server. Note that by '\n", + " 'convention we set the error code field within the message '\n", + " 'definition toerror_code.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'error_code_id_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'route_error_code_id',\n", + " 'context': 'In order to propagate your server’s error code to the rest of '\n", + " 'the system it must be added to the nav2_params.yaml file.\\n'\n", + " 'Theerror_code_id_namesinside of the BT Navigator define what '\n", + " 'error codes to look for on the blackboard by the server. The '\n", + " 'lowest error code of the sequence is then returned - whereas the '\n", + " 'code enums increase the higher up in the software stack - giving '\n", + " 'higher priority to lower-level failures.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: RotateToGoalCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": RotateToGoalCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Planner and Controller Servers\n", + "Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice.\n", + "The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment.\n", + "The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station.\n", + "As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server.\n", + "\n", + "## Selecting the Algorithm Plugins\n", + "In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server.\n", + "\n", + "## Planner Server\n", + "The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility.\n", + "As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments.\n", + "One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots.\n", + "Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds.\n", + "There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration.\n", + "\n", + "## Summary\n", + "\n", + "\n", + "## Example Configuration\n", + "An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Controller Server\n", + "The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity.\n", + "TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint.\n", + "Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots.\n", + "Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots.\n", + "The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots.\n", + "\n", + "## Summary\n", + "All of these algorithms work for both circular and non-circular robots.\n", + "\n", + "## Example Configuration\n", + "Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Non-circular Differential, Non-circular Omnidirectional',\n", + " 'filename': 'SmacLatticeplanner',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'All of these algorithms work for both circular and non-circular '\n", + " 'robots.',\n", + " 'filename': 'TrajectoryGenerationplugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: CancelBackUp\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'backup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: IsStuck\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Determines if the robot is not progressing towards the goal.\\n'\n", + " 'If the robot is stuck and not progressing, the condition '\n", + " 'returns\\n'\n", + " 'SUCCESS, otherwise it returns FAILURE.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Velocity Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Velocity Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'velocity_smoother\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'smoothing_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'scale_velocities\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'feedback\\n'\n", + " ':\\n'\n", + " '\"OPEN_LOOP\"\\n'\n", + " 'max_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '2.5\\n'\n", + " ']\\n'\n", + " 'min_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '-0.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '-2.5\\n'\n", + " ']\\n'\n", + " 'deadband_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'velocity_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'max_accel\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '2.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '3.2\\n'\n", + " ']\\n'\n", + " 'max_decel\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '-2.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '-3.2\\n'\n", + " ']\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'odom_duration\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_realtime_priority\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'false',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Roadmaps\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Jazzy Roadmap\n", + "\n", + "\n", + "## Iron Roadmap\n", + "\n", + "\n", + "## Humble Roadmap\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Setting Up the Robot’s Footprint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Footprint Introduction\n", + "The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans.\n", + "The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used.\n", + "For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization.\n", + "For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot.\n", + "Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Configuring the Robot’s Footprint\n", + "In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps.\n", + "Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot.\n", + "Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot.\n", + "For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We will now confirm that we have properly set upsam_bot’s footprint.\n", + "First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below.\n", + "After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor.\n", + "Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below.\n", + "Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors.\n", + "Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following:\n", + "We should now be able to visualize the footprints in RViz, which will be discussed in the next section.\n", + "\n", + "## Visualizing Footprint in RViz\n", + "To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot:\n", + "On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot:\n", + "\n", + "## Conclusion\n", + "In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function.\n", + "As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '188\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '189\\n'\n", + " 'footprint\\n'\n", + " ':\\n'\n", + " '\"[\\n'\n", + " '[0.21,\\n'\n", + " '0.195],\\n'\n", + " '[0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '0.195]\\n'\n", + " ']\"\\n'\n", + " '190\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Below is the code snippet fromnav2_params.yamldefining the local '\n", + " 'costmap footprint. In this configuration file, '\n", + " 'thefootprintparameter of the local costmap has already been set '\n", + " 'with a rectangular-shaped footprint. This box is centered at '\n", + " 'thebase_linkframe ofsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '232\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '233\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " '234\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': 'For the global costmap, we have already set '\n", + " 'therobot_radiusparameter to create a circular footprint that '\n", + " 'matchessam_bot’s size and centered atbase_link. The parameter '\n", + " 'that was modified is shown in the code snippet below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'First, we launchlaunch/display.launch.pyto launch the robot '\n", + " 'state publisher, spawnsam_botin Gazebo, and visualizesam_botand '\n", + " 'its footprint in Rviz. The robot state publisher publishes '\n", + " 'thebase_link=>sensorstransforms defined insam_bot’s URDF, while '\n", + " 'Gazebo’s differential drive plugin publishes '\n", + " 'theodom=>base_linktransform. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'map\\n'\n", + " 'odom\\n',\n", + " 'context': 'Next, we will publish themap=>odomtransform using '\n", + " 'thestatic_transform_publisher. We publish themap=>odomtransform '\n", + " 'as static in this guide as a simple way to publish the transform '\n", + " 'and visualize the footprint. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'navigation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '\\n',\n", + " 'context': 'Lastly, we will launch Nav2 using '\n", + " 'thenav2_params.yamlconfiguration file we just made '\n", + " 'andnavigation_launch.py, the built-in launch file '\n", + " 'ofnav2_bringup. Open a new terminal and execute the following:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dashing to Eloquent\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Packages\n", + "Navigation2 now includes a new packagenav2_waypoint_follower.\n", + "The waypoint follower is an action server that will take in a list of waypoints to follow and follow them in order.\n", + "There is a parameterstop_on_failurewhether the robot should continue to the next waypoint on a single waypoint failure,\n", + "or to return fail to the action client.\n", + "The waypoint follower is also a reference application for how to use the Navigation2 action server to complete a basic autonomy task.\n", + "Navigation2 now supports new algorithms for control and SLAM.\n", + "The Timed-Elastic Band (TEB) controller was implementedand can be found here.\n", + "It is its own controller plugin that can be used instead of the DWB controller.\n", + "Nav2 also supports SLAM Toolbox as the default SLAM implementation for ROS 2.\n", + "This replaces the use of Cartographer.\n", + "\n", + "## New Plugins\n", + "Eloquent introduces back in pluginlib plugins to the navigation stack.nav2_coredefines the plugin header interfaces to be used to implement controller, planner, recovery, and goal checker plugins.\n", + "All algorithms (NavFn, DWB, recoveries) were added as plugin interfaces and the general packages for servers were created.nav2_planneris the action server for planning that hosts a plugin for the planner.nav2_controlleris the action server for controller that hosts a plugin for the controller.nav2_recoveryis the action server for recovery that hosts a plugin for recovery.\n", + "New recovery plugins were added including backup, which will take in a distance to back up, if collision-free.\n", + "Additionally, the wait recovery was added that will wait a configurable period of time before trying to navigate again.\n", + "This plugin is especially helpful for time-dependent obstacles or pausing navigation for a scene to become less dynamic.\n", + "Many new behavior tree nodes were added. These behavior tree nodes are hard-coded in the behavior tree engine.\n", + "Behavior tree cpp v3 supports plugins and will be converted in the next release.\n", + "\n", + "## Navigation2 Architectural Changes\n", + "Thenav2_world_modelpackage was removed. The individualnav2_plannerandnav2_controllerservers now host their relevant costmaps.\n", + "This was done to reduce network traffic and ensure up-to-date information for the safety-critical elements of the system.\n", + "As above mentions, plugins were introduced into the stack and these servers each host plugins for navigation, control, and costmap layers.\n", + "Map server was substantially refactored but the external API remains the same. It now uses the SDL library for image loading.\n", + "TF-based positioning is now used for pose-estimation everywhere in the stack.\n", + "Prior, some elements of the navigation stack only updated its pose from the/amcl_posetopic publishing at an irregular rate.\n", + "This is obviously low-accuracy and high-latency.\n", + "All positioning is now based on the TF tree from the global frame to the robot frame.\n", + "Prior to Eloquent, there were no ROS 2 action servers and clients available.\n", + "Navigation2, rather, used an interface we called Tasks.\n", + "Eloquent now contains actions and a simple action server interface was created and is used now throughout the stack.\n", + "Tasks were removed.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: SmootherSelector\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The output selected Smoother id.',\n", + " 'filename': 'transientlocal',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Camera Calibration\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to obtain calibration parameters for monocular camera.\n", + "\n", + "## Requirements\n", + "1- Install Camera Calibration Parser, Camera Info Manager and Launch Testing Ament Cmake using operating system’s package manager:\n", + "2- Image Pipeline need to be built from source in your workspace with:\n", + "Also, make sure you have the following:\n", + "\n", + "## Tutorial Steps\n", + "1- Start a terminal in your GUI\n", + "2- Launch the ROS driver for your specific camera.\n", + "3- Make sure camera is publishing images over ROS. This can be tested by running:\n", + "4- This will show you all the topics published make sure that there is an image_raw topic /camera/image_raw. To confirm that its a real topic and actually publishing check topic hz:\n", + "5- Start the camera calibration node\n", + "6- In order to get a good calibration you will need to move the checkerboard around in the camera frame such that:\n", + "7- As the checkerboard is moved around the 4 bars on the calibration sidebar increases in length. When all then the 4 bars are green and enough data is available for calibration the CALIBRATE button will light up. Click it to see the results. It takes around the minute for calibration to take place.\n", + "8- After the calibration is completed the save and commit buttons light up. And you can also see the result in terminal.\n", + "9-Press the save button to see the result. Data is saved to “/tmp/calibrationdata.tar.gz”\n", + "11-In the folder images used for calibration are available and also “ost.yaml” and “ost.txt”. You can use the yaml file which contains the calibration parameters as directed by the camera driver.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Camera\\n'\n", + " 'Name\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'c\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'camera_name\\n'\n", + " 'name\\n'\n", + " 'of\\n'\n", + " 'the\\n'\n", + " 'camera\\n'\n", + " 'to\\n'\n", + " 'appear\\n'\n", + " 'in\\n'\n", + " 'the\\n'\n", + " 'calibration\\n'\n", + " 'file\\n'\n", + " 'Chessboard\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " 'You\\n'\n", + " 'must\\n'\n", + " 'specify\\n'\n", + " 'one\\n'\n", + " 'or\\n'\n", + " 'more\\n'\n", + " 'chessboards\\n'\n", + " 'as\\n'\n", + " 'pairs\\n'\n", + " 'of\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " 'and\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " 'options\\n'\n", + " '.\\n'\n", + " '-\\n'\n", + " 'p\\n'\n", + " 'PATTERN\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'pattern\\n'\n", + " '=\\n'\n", + " 'PATTERN\\n'\n", + " 'calibration\\n'\n", + " 'pattern\\n'\n", + " 'to\\n'\n", + " 'detect\\n'\n", + " '-\\n'\n", + " \"'chessboard'\\n\"\n", + " ',\\n'\n", + " \"'circles'\\n\"\n", + " ',\\n'\n", + " \"'acircles'\\n\"\n", + " ',\\n'\n", + " \"'charuco'\\n\"\n", + " '-\\n'\n", + " 's\\n'\n", + " 'SIZE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " '=\\n'\n", + " 'SIZE\\n'\n", + " 'chessboard\\n'\n", + " 'size\\n'\n", + " 'as\\n'\n", + " 'NxM\\n'\n", + " ',\\n'\n", + " 'counting\\n'\n", + " 'interior\\n'\n", + " 'corners\\n'\n", + " '(\\n'\n", + " 'e\\n'\n", + " '.\\n'\n", + " 'g\\n'\n", + " '.\\n'\n", + " 'a\\n'\n", + " 'standard\\n'\n", + " 'chessboard\\n'\n", + " 'is\\n'\n", + " '7\\n'\n", + " 'x7\\n'\n", + " ')\\n'\n", + " '-\\n'\n", + " 'q\\n'\n", + " 'SQUARE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " '=\\n'\n", + " 'SQUARE\\n'\n", + " 'chessboard\\n'\n", + " 'square\\n'\n", + " 'size\\n'\n", + " 'in\\n'\n", + " 'meters\\n'\n", + " 'ROS\\n'\n", + " 'Communication\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'approximate\\n'\n", + " '=\\n'\n", + " 'APPROXIMATE\\n'\n", + " 'allow\\n'\n", + " 'specified\\n'\n", + " 'slop\\n'\n", + " '(\\n'\n", + " 'in\\n'\n", + " 'seconds\\n'\n", + " ')\\n'\n", + " 'when\\n'\n", + " 'pairing\\n'\n", + " 'images\\n'\n", + " 'from\\n'\n", + " 'unsynchronized\\n'\n", + " 'stereo\\n'\n", + " 'cameras\\n'\n", + " '--\\n'\n", + " 'no\\n'\n", + " '-\\n'\n", + " 'service\\n'\n", + " '-\\n'\n", + " 'check\\n'\n", + " 'disable\\n'\n", + " 'check\\n'\n", + " 'for\\n'\n", + " 'set_camera_info\\n'\n", + " 'services\\n'\n", + " 'at\\n'\n", + " 'startup\\n'\n", + " 'Calibration\\n'\n", + " 'Optimizer\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'principal\\n'\n", + " '-\\n'\n", + " 'point\\n'\n", + " 'fix\\n'\n", + " 'the\\n'\n", + " 'principal\\n'\n", + " 'point\\n'\n", + " 'at\\n'\n", + " 'the\\n'\n", + " 'image\\n'\n", + " 'center\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'aspect\\n'\n", + " '-\\n'\n", + " 'ratio\\n'\n", + " 'enforce\\n'\n", + " 'focal\\n'\n", + " 'lengths\\n'\n", + " '(\\n'\n", + " 'fx\\n'\n", + " ',\\n'\n", + " 'fy\\n'\n", + " ')\\n'\n", + " 'are\\n'\n", + " 'equal\\n'\n", + " '--\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'tangent\\n'\n", + " '-\\n'\n", + " 'dist\\n'\n", + " 'set\\n'\n", + " 'tangential\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " '(\\n'\n", + " 'p1\\n'\n", + " ',\\n'\n", + " 'p2\\n'\n", + " ')\\n'\n", + " 'to\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'k\\n'\n", + " 'NUM_COEFFS\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'k\\n'\n", + " '-\\n'\n", + " 'coefficients\\n'\n", + " '=\\n'\n", + " 'NUM_COEFFS\\n'\n", + " 'number\\n'\n", + " 'of\\n'\n", + " 'radial\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " 'to\\n'\n", + " 'use\\n'\n", + " '(\\n'\n", + " 'up\\n'\n", + " 'to\\n'\n", + " '6\\n'\n", + " ',\\n'\n", + " 'default\\n'\n", + " '2\\n'\n", + " ')\\n'\n", + " '--\\n'\n", + " 'disable_calib_cb_fast_check\\n'\n", + " 'uses\\n'\n", + " 'the\\n'\n", + " 'CALIB_CB_FAST_CHECK\\n'\n", + " 'flag\\n'\n", + " 'for\\n'\n", + " 'findChessboardCorners\\n'\n", + " 'This\\n'\n", + " 'will\\n'\n", + " 'open\\n'\n", + " 'a\\n'\n", + " 'calibration\\n'\n", + " 'window\\n'\n", + " 'which\\n'\n", + " 'highlight\\n'\n", + " 'the\\n'\n", + " 'checkerboard\\n'\n", + " '.',\n", + " 'context': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'filename': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Detailed Behavior Tree Walkthrough\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document serves as a reference guide to the main behavior tree (BT) used in Nav2.\n", + "There are many example behavior trees provided innav2_bt_navigator/behavior_trees,\n", + "but these sometimes have to be re-configured based on the application of the robot.\n", + "The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail.\n", + "\n", + "## Prerequisites\n", + "\n", + "\n", + "## Navigate To Pose With Replanning and Recovery\n", + "The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml.\n", + "This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions.\n", + "BTs are primarily defined in XML. The tree shown above is represented in XML as follows.\n", + "This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time.\n", + "These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree.\n", + "This can be represented in the following way:\n", + "TheNavigationsubtree mainly involves actual navigation behavior:\n", + "TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally.\n", + "The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail\n", + "(path calculation or path following), contextual recoveries will be attempted.\n", + "If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE.\n", + "The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures.\n", + "This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6).\n", + "\n", + "## Navigation Subtree\n", + "Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree.\n", + "The XML of this subtree is as follows:\n", + "This subtree has two primary actionsComputePathToPoseandFollowPath.\n", + "If either of these two actions fail, they will attempt to clear the failure contextually.\n", + "The crux of the tree can be represented with only one parent and two children nodes like this:\n", + "The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked.\n", + "While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around.\n", + "Both theComputePathToPoseand theFollowPathfollow the same general structure.\n", + "The below is theComputePathToPosesubtree:\n", + "The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree.\n", + "The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap.\n", + "Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries.\n", + "The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below:\n", + "\n", + "## Recovery Subtree\n", + "TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree.\n", + "In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient).\n", + "And the XML snippet:\n", + "The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received.\n", + "If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries.\n", + "This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”.\n", + "These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree\n", + "in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge).\n", + "If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are:\n", + "UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree.\n", + "If this renavigation was not successful, the next child of theRoundRobinwill be ticked.\n", + "For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE:\n", + "(for the sake of this example, let’s assume that the goal is never updated).\n", + "If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure).\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'BTs are primarily defined in XML. The tree shown above is '\n", + " 'represented in XML as follows.',\n", + " 'filename': 'navigate_to_pose_w_replanning_and_recovery.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'This happens until thenumber_of_retriesfor the '\n", + " 'parentRecoveryNodeis exceeded (which by default is 6).',\n", + " 'filename': 'RecoveryNode',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The XML of this subtree is as follows:',\n", + " 'filename': 'Recovery',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'And the XML snippet:',\n", + " 'filename': 'Navigation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior-Tree Navigator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " 'replace/with/path/to/bt.xml\\n'\n", + " '# or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " 'default_nav_through_poses_bt_xml\\n'\n", + " ':\\n'\n", + " 'replace/with/path/to/bt.xml\\n'\n", + " '# or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " 'always_reload_bt_xml\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'goal_blackboard_id\\n'\n", + " ':\\n'\n", + " 'goal\\n'\n", + " 'goals_blackboard_id\\n'\n", + " ':\\n'\n", + " 'goals\\n'\n", + " 'path_blackboard_id\\n'\n", + " ':\\n'\n", + " 'path\\n'\n", + " 'navigators\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'navigate_to_pose'\\n\"\n", + " ',\\n'\n", + " \"'navigate_through_poses'\\n\"\n", + " ']\\n'\n", + " 'navigate_to_pose\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_bt_navigator::NavigateToPoseNavigator\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'navigate_through_poses\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_bt_navigator::NavigateThroughPosesNavigator\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'plugin_lib_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'nav2_compute_path_to_pose_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_follow_path_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_back_up_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_spin_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_wait_action_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_clear_costmap_service_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_is_stuck_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_is_stopped_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_goal_reached_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_initial_pose_received_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_goal_updated_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_reinitialize_global_localization_service_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_rate_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_distance_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_speed_controller_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_recovery_node_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_pipeline_sequence_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_round_robin_node_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_transform_available_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_time_expired_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_distance_traveled_condition_bt_node\\n'\n", + " '-\\n'\n", + " 'nav2_single_trigger_bt_node\\n'\n", + " 'error_code_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code\\n'\n", + " '# - smoother_error_code, navigate_to_pose_error_code, '\n", + " 'navigate_through_poses_error_code, etc',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'NavigateThroughPoses',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use.\n", + "Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package.\n", + "\n", + "## What is the Rotation Shim Controller?\n", + "This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers.\n", + "Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so.\n", + "Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task.\n", + "TheRotationShimControlleris most suitable for:\n", + "\n", + "## Configuring Rotation Shim Controller\n", + "This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through.\n", + "As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel.\n", + "The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted.\n", + "\n", + "## Configuring Primary Controller\n", + "There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity).\n", + "An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform.\n", + "\n", + "## Demo Execution\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'As such, its configuration looks very similar to that of any '\n", + " 'other plugin. In the code block below, you can see that we’ve '\n", + " 'added theRotationShimControlleras the plugin for path tracking '\n", + " 'in the controller server. You can see that we’ve also configured '\n", + " 'it below with its internal '\n", + " 'parameters,angular_dist_thresholdthroughmax_angular_accel.',\n", + " 'filename': 'max_angular_accel',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# DWB parameters\\n'\n", + " '...\\n'\n", + " '...\\n'\n", + " '...',\n", + " 'context': 'There is one more remaining parameter of '\n", + " 'theRotationShimControllernot mentioned above, '\n", + " 'theprimary_controller. This is the type of controller that your '\n", + " 'application would like to use as the primary modus operandi. It '\n", + " 'will share the same name and yaml namespace as the shim plugin. '\n", + " 'You can observe this below with the primary controller set '\n", + " 'theDWB(with the progress and goal checkers removed for brevity).',\n", + " 'filename': 'DWB',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Regulated Pure Pursuit\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Regulated Pure Pursuit Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController\"\\n'\n", + " 'desired_linear_vel\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'min_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'max_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'lookahead_time\\n'\n", + " ':\\n'\n", + " '1.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_velocity_scaled_lookahead_dist\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'min_approach_linear_velocity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'approach_velocity_scaling_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'use_collision_detection\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_allowed_time_to_collision_up_to_carrot\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'use_regulated_linear_velocity_scaling\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_fixed_curvature_lookahead\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'curvature_lookahead_dist\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'use_cost_regulated_linear_velocity_scaling\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'regulated_linear_scaling_min_radius\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'regulated_linear_scaling_min_speed\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'use_rotate_to_heading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'allow_reversing\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotate_to_heading_min_angle\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'max_robot_pose_search_dist\\n'\n", + " ':\\n'\n", + " '10.0',\n", + " 'context': 'Note: Needsuse_fixed_curvature_lookaheadto betrue',\n", + " 'filename': 'true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Graceful Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Graceful Controller Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " 'nav2_graceful_controller::GracefulController\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'motion_target_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'initial_rotation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'initial_rotation_min_angle\\n'\n", + " ':\\n'\n", + " '0.75\\n'\n", + " 'final_rotation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'allow_backward\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'beta\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'lambda\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'v_angular_max\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'slowdown_radius\\n'\n", + " ':\\n'\n", + " '1.5',\n", + " 'context': 'Whether to allow the robot to move backward.',\n", + " 'filename': 'initial_rotation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dynamic Object Following\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely.\n", + "This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application:\n", + "The requirements for this task are as follows:\n", + "The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest,\n", + "send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Create the Behavior Tree\n", + "Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow:\n", + "First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node.\n", + "We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received.\n", + "To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance.\n", + "Now, you may save this behavior tree and use it in our navigation task.\n", + "For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage.\n", + "\n", + "## 1- Setup Rviz clicked point\n", + "We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to\n", + "publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone\n", + "this repo in your workspace, build, and type in a terminal.\n", + "ros2runnav2_test_utilsclicked_point_to_pose\n", + "Optionally, you can remap this topic in your rviz configuration file togoal_updates.\n", + "\n", + "## 2- Run Dynamic Object Following in Nav2 Simulation\n", + "Start Nav2 in one terminal:\n", + "ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml\n", + "Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial.\n", + "When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest!\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Let’s start from this simple behavior tree. This behavior tree '\n", + " 'replans a new path at 1 hz and passes that path to the '\n", + " 'controller to follow:',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'First, let’s make this behavior run until there’s a failure. For '\n", + " 'this purpose, we will use theKeepRunningUntilFailurecontrol '\n", + " 'node.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'We will then use the decoratorGoalUpdaterto accept updates of '\n", + " 'the dynamic object pose we’re trying to follow. This node takes '\n", + " 'as input the current goal and subscribes to the '\n", + " 'topic/goal_update. It sets the new goal asupdated_goalif a new '\n", + " 'goal on that topic is received.',\n", + " 'filename': 'updated_goal',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To stay at a certain distance from the target, we will use the '\n", + " 'action nodeTruncatePath. This node modifies a path making it '\n", + " 'shorter so we don’t try to navigate into the object of interest. '\n", + " 'We can set up the desired distance to the goal using the input '\n", + " 'portdistance.',\n", + " 'filename': 'distance',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: NavFn Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'use_astar\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'allow_unknown\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'If true, the last pose of the path generated by the planner will '\n", + " 'have its orientation set to the approach orientation, i.e. the '\n", + " 'orientation of the vector connecting the last two points of the '\n", + " 'path',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Rotation Shim Controller Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'rotate_to_goal_heading\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Primary controller params can be placed here below\\n'\n", + " '# ...',\n", + " 'context': 'If true, the rotationShimController will only rotate to heading '\n", + " 'once on a new goal, not each time a path is set.',\n", + " 'filename': 'README',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Transformations\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Transforms Introduction\n", + "Many ROS packages require the transform tree of a robot to be published using the TF2 ROS package. A transformation tree defines the relations between different coordinate systems, in terms of translation, rotation, and relative motion. To make this more concrete, let us apply an example of a simple robot that has a mobile base with a single laser sensor mounted on top of it.\n", + "This robot has two defined coordinate frames: one corresponding to the center point of the mobile base of the robot, and one for the center point of the laser that is mounted on top of the base. We’ll call the coordinate frame attached to the mobile basebase_linkand we’ll call the coordinate frame attached to the laserbase_laser. Note that will be talking more about the naming and conventions of these coordinate frames in the next section.\n", + "At this point, let’s assume that we have some data from the laser in the form of distance measurements from the laser’s center point. In other words, we have some data in thebase_lasercoordinate frame.\n", + "Now, suppose we want to take this data and use it to help the mobile base avoid obstacles in the world. To do this successfully, we need a way to transform the laser scan we’ve received from thebase_laserframe to thebase_linkframe. In essence, we need to define a relationship between thebase_laserandbase_linkcoordinate frames.\n", + "In defining this relationship, let us assume that the only data we have is that the laser is mounted 10cm forward and 20cm above the center point of the mobile base. This gives us a translational offset that relates thebase_linkframe to thebase_laserframe. Specifically, we know that to get data from thebase_linkframe to thebase_laserframe, we must apply a translation of (x: 0.1m, y: 0.0m, z: 0.2m), and transversely, to get data from thebase_laserframe to thebase_linkframe, we must apply the opposite translation (x: -0.1m, y: 0.0m, z: -0.20m).\n", + "We could choose to manage this relationship ourselves, meaning to store and apply the appropriate translations between the frames when necessary, but this becomes a real pain as the number of coordinate frames increases. Luckily, we don’t have to do this work ourselves. Instead, we’ll define the relationship betweenbase_linkandbase_laseronce using TF2 and let it manage the transformation between the two coordinate frames for us. This is especially useful when working with non-static transformations, such as a set of frames that are moving relative to each other, like a robot base frame in a map frame.\n", + "To define and store the relationship between thebase_linkandbase_laserframes using TF2, we need to add them to a transform tree. Conceptually, each node in the transform tree corresponds to a coordinate frame, and each edge corresponds to the transform that needs to be applied to move from the current node to its child. TF2 uses a tree structure to guarantee that there is only a single traversal that links any two coordinate frames together, and assumes that all edges in the tree are directed from parent to child nodes.\n", + "To create a transform tree for our simple example, we’ll create two nodes: one for thebase_linkcoordinate frame and one for thebase_lasercoordinate frame. To create the edge between them, we first need to decide which node will be the parent and which will be the child. Remember — this distinction is important because TF2 assumes that all transforms move from parent to child.\n", + "Let’s choose thebase_linkcoordinate frame as the parent because when other pieces/sensors are added to the robot, it will make the most sense for them to relate to thebase_laserframe by traversing through thebase_linkframe. This means that the transform associated with the edge connectingbase_linkandbase_lasershould be (x: 0.1m, y: 0.0m, z: 0.2m).\n", + "With this transform tree set up, converting the laser scan received in thebase_laserframe to thebase_linkframe is as simple as making a call to the TF2 library. Our robot can now use this information to reason about laser scans in thebase_linkframe and safely plan around obstacles in its environment.\n", + "\n", + "## Static Transform Publisher Demo\n", + "Now let’s try publishing a very simple transform using the static_transform_publisher tool provided by TF2. We will be publishing a transformation from the linkbase_linkto the linkbase_laserwith a translation of (x: 0.1m, y: 0.0m, z: 0.2m). Note that we will be building the transform from the diagram earlier in this tutorial.\n", + "Open up your command line and execute the following command:\n", + "With this, we are now successfully publishing ourbase_linktobase_lasertransform in TF2. Let us now check if it is working properly throughtf2_echo. Open up a separate command line window and execute the following:\n", + "You should be able to observe a repeated output similar to the one below.\n", + "And that’s it for this short demo - we were able to successfully publish a transform frombase_linktobase_laserusing the TF2 library. Note that we do not recommend using the above demo in publishing transforms for your actual robotics projects, it is just a quick demo to see TF2 in action. For a real robot system, we would create a URDF file which embeds this information and more about your robot for use of the robot_state_publisher rather than the static_transform_publisher. There are more suitable and practical ways to go about this which will be discussed in theSetting Up The URDFtutorial.\n", + "\n", + "## Transforms in Navigation2\n", + "There are two important ROS REPs which we highly suggest for you to check out. These documents detail some standards set about by the ROS community to ensure proper operation across different packages. Nav2 also adheres to these standards and conventions.\n", + "To quickly summarize REP 105, this document specifies the naming conventions and semantic meanings of the different coordinate frames used in ROS. Of interest to this tutorial are thebase_link,odomandmapcoordinate frames. Thebase_linkis a coordinate frame that is attached to a fixed position on the robot, typically at its main chassis and its rotational center. Theodomcoordinate frame is a fixed frame relative to the robot’s starting position and is mainly used for locally-consistent representations of distances. Lastly, themapcoordinate frame is a world fixed frame that is used for globally-consistent representations of distances.\n", + "REP 103, on the other hand, discusses some standard units of measure and other related conventions to keep integration issues between different ROS packages to a minimum. The basic overview is that frames are defined using the right hand rule, with Z up and X forward, and units should be standard SI units.\n", + "Now let’s move on to some specifics for the Navigation2 package to function correctly. Nav2 requires the following transformations to be published in ROS:\n", + "The first transformmap=>odomis usually provided by a different ROS package dealing with localization and mapping such as AMCL. This transform updates live in use so we don’t set static values for this in our robot’s TF tree. Further detail about how to set this up may be pretty complex, so we highly suggest to have a look at the documentation of the mapping or localization package you are using for your platform. All ROS compliant SLAM and localization packages will provide you with this transformation automatically on launch.\n", + "Theodom=>base_linkis usually published by our odometry system using sensors such as wheel encoders. This is typically computed via sensor fusion of odometry sensors (IMU, wheel encoders, VIO, etc) using therobot_localizationpackage.\n", + "All other statically defined transforms (e.g.base_link=>base_laser,base_link=>wheels,wheels=>IMU, etc) is what we will be talking about for the rest of this guide. This transformation tree is used by Nav2 to properly relate the information from sensors or other frame of interest to the rest of the robot. The transformation between these two coordinate frames is usually provided to Nav2 through the Robot State Publisher and the Universal Robot Descriptor File (URDF). In cases where there are more sensor coordinate frames on your platform, then a transform tree frombase_linkto each sensor coordinate frame needs to be published.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed about the concept of transforms and how they are used in Nav2.\n", + "In the last section, we have also explored using the static_transform_publisher of TF2 to publish our transforms. You may use this to set up your transforms for Nav2, but this is generally not the best way to do it. In most robotics projects, we make use of the Robot State Publisher since it is much easier to use and scales well as our robot gets more complex. We will be talking about the Robot State Publisher, URDF, and how to set it up in the next tutorial onSetting Up The URDF.\n", + "Lastly, we also discussed the three published transform requirements of Nav2 and the necessary REPs to keep in mind when setting them up.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '.1\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '.2\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'base_link\\n'\n", + " 'base_laser\\n',\n", + " 'context': 'Open up your command line and execute the following command:',\n", + " 'filename': 'base_laser',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nbase_link\\nbase_laser\\n',\n", + " 'context': 'With this, we are now successfully publishing '\n", + " 'ourbase_linktobase_lasertransform in TF2. Let us now check if it '\n", + " 'is working properly throughtf2_echo. Open up a separate command '\n", + " 'line window and execute the following:',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '0\\n'\n", + " '.0\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.100,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.200\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '1\\n'\n", + " '.000\\n'\n", + " ']',\n", + " 'context': 'You should be able to observe a repeated output similar to the '\n", + " 'one below.',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Provided Nodes\n", + "The nodes listed below are inside thenav2_collision_monitorpackage. See the pages for individual configuration information.\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Migration Guides\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: WouldASmootherRecoveryHelp\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Port\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The active error code to compare against. This should match the '\n", + " 'smoother server error code.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smac Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Description\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. It uses template node types to develop different search-based planners.\n", + "We support circular differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support car-like (ackermann) and legged vehicles using theSmacPlannerHybridplugin which implements a Hybrid-A* planner. We support non-circular, arbitrary shaped, any model vehicles using theSmacPlannerLatticeplugin which implements a State Lattice planner (e.g. omni, diff, ackermann, legged, custom). It contains control sets and generators for ackermann, legged, differential drive and omnidirectional vehicles, but you may provide your own for another robot type or to have different planning behaviors.\n", + "The last two plugins are bothkinematically feasibleand supportreversing. They have performance similar to its 2D counter parts like 2D-A* and NavFn via highly optimized heuristic functions and efficient programming. An example of the 3 planners can be seen below, planning a roughly 75 m path.\n", + "Usual planning times are below 100ms for some environments, occasionally approaching up to 200ms. The performance of all 3 planners is roughly comparable with naive 2D search algorithms that have long been mainstays of the ROS Navigation ecosystem, but also achieving kinematic feasibility, support for reversing, and using modern state of the art techniques.\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GoalCheckerSelector\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The output selected GoalChecker id. This selected_goal_checker '\n", + " 'string is usually passed to the FollowPath behavior via the '\n", + " 'goal_checker_id input port.',\n", + " 'filename': 'transientlocal',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DWB Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Controller\n", + "\n", + "\n", + "## Plugins\n", + "The plugins listed below are inside thedwb_pluginsnamespace.\n", + "\n", + "## Trajectory Critics\n", + "The trajectory critics listed below are inside thedwb_criticsnamespace.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# controller server parameters (see Controller Server for more '\n", + " 'info)\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# DWB controller parameters\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'debug_trajectory_details\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'min_vel_x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'min_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'max_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_theta\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_speed_xy\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_speed_xy\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'min_speed_theta\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_x\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'acc_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_theta\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'decel_lim_x\\n'\n", + " ':\\n'\n", + " '-2.5\\n'\n", + " 'decel_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'decel_lim_theta\\n'\n", + " ':\\n'\n", + " '-3.2\\n'\n", + " 'vx_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'vy_samples\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'vtheta_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'sim_time\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'linear_granularity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'angular_granularity\\n'\n", + " ':\\n'\n", + " '0.025\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'trans_stopped_velocity\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'short_circuit_trajectory_evaluation\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'limit_vel_cmd_in_traj\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"RotateToGoal\"\\n'\n", + " ',\\n'\n", + " '\"Oscillation\"\\n'\n", + " ',\\n'\n", + " '\"BaseObstacle\"\\n'\n", + " ',\\n'\n", + " '\"GoalAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathDist\"\\n'\n", + " ',\\n'\n", + " '\"GoalDist\"\\n'\n", + " ']\\n'\n", + " 'BaseObstacle.scale\\n'\n", + " ':\\n'\n", + " '0.02\\n'\n", + " 'PathAlign.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalAlign.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'PathAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'GoalAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'PathDist.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalDist.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'RotateToGoal.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'RotateToGoal.slowing_factor\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'RotateToGoal.lookahead_time\\n'\n", + " ':\\n'\n", + " '-1.0',\n", + " 'context': 'The trajectory critics listed below are inside '\n", + " 'thedwb_criticsnamespace.',\n", + " 'filename': 'dwb_critics',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: NavigateToPose\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '/behavior_trees/navigate_through_poses_w_replanning_and_recovery.xml\"\\n'\n", + " '/>',\n", + " 'context': 'The lowest error code in the list of '\n", + " 'theerror_code_namesparameter.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a New Nav2 Task Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Lifecycle Nodes\n", + "The Lifecycle node is the first key component of a nav2 task server. Lifecycle nodes were introduced in ROS 2 to systematically manage the bringup and shutdown of the different nodes involved in the robot’s operation. The use of Lifecycle nodes ensures that all nodes are successfully instantiated before they begin their execution and Nav2 shuts down all nodes if there is any unresponsive node.\n", + "Lifecycle nodes contain state machine transitions that enable deterministic behavior in ROS 2 servers. The Lifecycle node transitions in Nav2 are handled by theLifecycleManager. The Lifecycle Manager transitions the states of the Lifecycle nodes and provides greater control over the state of a system.\n", + "The primary states of a Lifecycle node areUnconfigured,Inactive,Active, andFinalized. A Lifecycle node starts in anUnconfiguredstate after being instantiated. The Lifecycle Manager transitions a node fromUnconfiguredtoInactiveby implementing theConfiguratingtransition. TheConfiguratingtransition sets up all configuration parameters and prepares any required setup such as memory allocation and the set up of the static publication and subscription topics. A node in theInactivestate is allowed to reconfigure its parameters and but cannot perform any processing. From theInactivestate, the Lifecycle Manager implements theActivatingtransition state to transition the node fromInactivetoActive, which is the main state. A node in theActivestate is allowed to perform any processing operation. In case a node crashes, the Lifecycle Manager shuts down the system to prevent any critical failures. On shutdown, the necessary cleanup operations are performed and the nodes are transitioned to theFinalizedstate viaDeactivating,CleaningUp, andShuttingDowntransition states.\n", + "You may wish to integrate your own nodes into the Nav2 framework or add new lifecycle nodes to your system. As an example, we will add a new notional lifecycle nodesensor_driver, and have it be controlled via the Nav2 Lifecycle Manager to ensure sensor feeds are available before activating navigation. You can do so by adding asensor_drivernode in your launch file and adding it to the list of nodes to be activated by thelifecycle_managerbefore navigation, as shown in the example below.\n", + "In the snippet above, the nodes to be handled by the Lifecycle Manager are set using thenode_namesparameter. Thenode_namesparameter takes in an ordered list of nodes to bringup through the Lifecycle transition. As shown in the snippet, thenode_namesparameter takes inlifecycle_nodeswhich contains the list of nodes to be added to the Lifecycle Manager. The Lifecycle Manager implements bringup transitions (ConfiguringandActivating) to the nodes one-by-one and in order, while the nodes are processed in reverse order for shutdown transitions. Hence, thesensor_driveris listed first before the other navigation servers so that the sensor data is available before the navigation servers are activated.\n", + "Two other parameters of the Lifecycle Manager areautostartandbond_timeout. Setautostarttotrueif you want to set the transition nodes to theActivestate on startup. Otherwise, you will need to manually trigger Lifecycle Manager to transition up the system. Thebond_timeoutsets the waiting time to decide when to transition down all of the nodes if a node is not responding.\n", + "\n", + "## Composition\n", + "Composition is the second key component nav2 task servers that was introduced to reduce the memory and CPU resources by putting multiple nodes in a single process. In Nav2, Composition can be used to compose all Nav2 nodes in a single process instead of launching them separately. This is useful for deployment on embedded systems where developers need to optimize resource usage.\n", + "In the following section, we give an example on how to add a new Nav2 server, which we notionally call theroute_server, to our system.\n", + "We make use of the launch files to compose different servers into a single process. The process is established by theComposableNodeContainercontainer that is populated with composition nodes viaComposableNode. This container can then be launched and used the same as any other Nav2 node.\n", + "\n", + "## Error codes\n", + "Your nav2 task server may also wish to return a ‘error_code’ in its action response (though not required). If there are semantically meaningful and actionable types of failures for your system, this is a systemic way to communicate those failures which may be automatically aggregated into the responses of the navigation system to your application.\n", + "It is important to note that error codes from 0-9999 are reserved for internal nav2 servers with each server offset by 100 while external servers start at 10000 and end at 65535.\n", + "The table below shows the current servers along with the expected error code structure.\n", + "Error codes are attached to the response of the action message. An example can be seen below for the route server. Note that by convention we set the error code field within the message definition toerror_code.\n", + "As stated in the message, the priority order of the errors should match the message order, 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "Since the the route server is a external server, the errors codes start at 10000 and go up to 10099.\n", + "In order to propagate your server’s error code to the rest of the system it must be added to the nav2_params.yaml file.\n", + "Theerror_code_id_namesinside of the BT Navigator define what error codes to look for on the blackboard by the server. The lowest error code of the sequence is then returned - whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "\n", + "## Conclusion\n", + "In this section of the guide, we have discussed Lifecycle Nodes, Composition and Error Codes which are new and important concepts in ROS 2. We also showed how to implement Lifecycle Nodes, Composition and Error Codes to your newly created nodes/servers with Nav2. These three concepts are helpful to efficiently run your system and therefore are encouraged to be used throughout Nav2.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'smoother_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " '...\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_navigation'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),',\n", + " 'context': 'You may wish to integrate your own nodes into the Nav2 framework '\n", + " 'or add new lifecycle nodes to your system. As an example, we '\n", + " 'will add a new notional lifecycle nodesensor_driver, and have it '\n", + " 'be controlled via the Nav2 Lifecycle Manager to ensure sensor '\n", + " 'feeds are available before activating navigation. You can do so '\n", + " 'by adding asensor_drivernode in your launch file and adding it '\n", + " 'to the list of nodes to be activated by '\n", + " 'thelifecycle_managerbefore navigation, as shown in the example '\n", + " 'below.',\n", + " 'filename': 'lifecycle_manager',\n", + " 'language': 'unknown'},\n", + " {'code': 'container\\n'\n", + " '=\\n'\n", + " 'ComposableNodeContainer\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'my_container'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rclcpp_components'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'component_container'\\n\"\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server::RouteServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " '),\\n'\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " ')',\n", + " 'context': 'Add a newComposableNode()instance in your launch file pointing '\n", + " 'to the component container of your choice.',\n", + " 'filename': 'ComposableNode()',\n", + " 'language': 'unknown'},\n", + " {'code': '\\nnav2_route_server\\n',\n", + " 'context': 'Add the package containing the server to yourpackage.xmlfile.',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '# Error codes\\n'\n", + " '# Note: The expected priority order of the errors should match the '\n", + " 'message order\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'NONE\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " '# 0 is reserved for NONE\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'UNKNOWN\\n'\n", + " '=\\n'\n", + " '10000\\n'\n", + " '# first error code in the sequence is reserved for UNKNOWN\\n'\n", + " '# User Error codes below\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'INVALID_START\\n'\n", + " '=\\n'\n", + " '10001\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'NO_VALID_ROUTE\\n'\n", + " '=\\n'\n", + " '10002\\n'\n", + " '#goal definition\\n'\n", + " '\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'goal\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'start\\n'\n", + " 'string\\n'\n", + " 'route_id\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'nav_msgs/Route\\n'\n", + " 'route\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'route_time\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '---\\n',\n", + " 'context': 'Error codes are attached to the response of the action message. '\n", + " 'An example can be seen below for the route server. Note that by '\n", + " 'convention we set the error code field within the message '\n", + " 'definition toerror_code.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'error_code_id_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'route_error_code_id',\n", + " 'context': 'In order to propagate your server’s error code to the rest of '\n", + " 'the system it must be added to the nav2_params.yaml file.\\n'\n", + " 'Theerror_code_id_namesinside of the BT Navigator define what '\n", + " 'error codes to look for on the blackboard by the server. The '\n", + " 'lowest error code of the sequence is then returned - whereas the '\n", + " 'code enums increase the higher up in the software stack - giving '\n", + " 'higher priority to lower-level failures.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Costmap 2D\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Costmap2D ROS Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thepluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Plugin Parameters\n", + "\n", + "\n", + "## Costmap Filters Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ',\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'footprint_padding\\n'\n", + " ':\\n'\n", + " '0.03\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '# radius set and used, so no footprint points\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " '# no frame set, uses frame from message\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"PointCloud2\"\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'subscribe_to_updates\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'inflate_unknown\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'inflate_around_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': '“nav2_costmap_2d::InflationLayer”',\n", + " 'filename': 'plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Our Sponsors\n", + "\n", + "\n", + "## Services\n", + "If you need professional services related to Nav2, please contact Open Navigation atinfo@opennav.org.\n", + "\n", + "## Overview\n", + "Nav2 is the professionally-supported successor of the ROS Navigation Stack deploying the same kinds of technology powering Autonomous Vehicles brought down, optimized, and reworked for mobile and surface robotics.\n", + "This project allows for mobile robots to navigate through complex environments to complete user-defined application tasks with nearly any class of robot kinematics.\n", + "Not only can it move from Point A to Point B, but it can have intermediary poses, and represent other types of tasks like object following, complete coverage navigation, and more.\n", + "Nav2 is a production-grade and high-quality navigation framework trusted by 100+ companies worldwide.\n", + "It provides perception, planning, control, localization, visualization, and much more to build highly reliable autonomous systems.\n", + "This will compute an environmental model from sensor and semantic data, dynamically path plan, compute velocities for motors, avoid obstacles, and structure higher-level robot behaviors.\n", + "To learn more about this project, such as related projects, robots using, ROS1 comparison, and maintainers, seeAbout and Contact.\n", + "To learn more about navigation and ROS concepts, seeNavigation Concepts.\n", + "Nav2 uses behavior trees to create customized and intelligent navigation behavior via orchestrating many independent modular servers.\n", + "A task server can be used to compute a path, control effort, behavior, or any other navigation\n", + "related task. These separate servers communicate with the behavior tree (BT)\n", + "over a ROS interface such as an action server or service.\n", + "A robot may utilize potentially many different behavior trees to allow a robot to perform many types of unique and complex tasks.\n", + "The diagram below will give you a good first-look at the structure of Nav2.\n", + "Note that it is possible to have multiple plugins for controllers, planners,\n", + "and recoveries in each of their servers. This can be used to create contextual navigation behaviors.\n", + "Each of the servers also returns status indicators back to the BT Navigator in order to enact contextual behaviors based on their results.\n", + "The expected inputs to Nav2 are TF transformations conforming to REP-105, a\n", + "map source if utilizing the Static Costmap Layer, a BT XML file, and any relevant sensor data\n", + "sources. It will then provide valid velocity commands for the motors of a holonomic or\n", + "non-holonomic robot to follow when properly configured. We currently support all of the major robot types:\n", + "holonomic, differential-drive, legged, and ackermann (car-like) base types! We support\n", + "them uniquely with both circular and arbitrarily-shaped robots for SE2 collision checking.\n", + "It has tools to:\n", + "We also provide a set of starting plugins to get you going.\n", + "A list of all plugins can be found onNavigation Plugins- but they include algorithms for the spanning cross section of common behaviors and robot platform types.\n", + "\n", + "## Related Projects\n", + "Check out related projects to Nav2:\n", + "\n", + "## Citations\n", + "If you use the navigation framework, an algorithm from this repository, or ideas from it\n", + "please cite this work in your papers!\n", + "S. Macenski, F. Martín, R. White, J. Clavero.The Marathon 2: A Navigation System.\n", + "IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2020.\n", + "IROS 2020 talk on Nav2 Marathon Experiments:\n", + "If you use any of the algorithms in Nav2 or the analysis of the algorithms in your work, please cite this work in your papers!\n", + "S. Macenski, T. Moore, DV Lu, A. Merzlyakov, M. Ferguson,From the desks of ROS maintainers: A survey of modern & capable mobile robotics algorithms in the robot operating system 2,\n", + "Robotics and Autonomous Systems, 2023\n", + "Smac Planner (Hybrid A*, State Lattice, 2D):\n", + "S. Macenski, M. Booker, J. Wallace,Open-Source, Cost-Aware Kinematically Feasible Planning for Mobile and Surface Robotics,\n", + "Regulated Pure Pursuit Controller:\n", + "S. Macenski, S. Singh, F. Martin, J. Gines,Regulated Pure Pursuit for Robot Path Tracking,\n", + "Autonomous Robots, 2023.\n", + "VSLAM and formal comparisons for service robot needs:\n", + "A. Merzlyakov, S. Macenski.A Comparison of Modern General-Purpose Visual SLAM Approaches.\n", + "IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2021.\n", + "\n", + "Code Blocks:\n", + "[{'code': '@InProceedings\\n'\n", + " '{\\n'\n", + " 'macenski2020marathon2,\\n'\n", + " '\\n'\n", + " 'author\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'Macenski,\\n'\n", + " 'Steven\\n'\n", + " 'and\\n'\n", + " 'Martin,\\n'\n", + " 'Francisco\\n'\n", + " 'and\\n'\n", + " 'White,\\n'\n", + " 'Ruffin\\n'\n", + " 'and\\n'\n", + " 'Ginés\\n'\n", + " 'Clavero,\\n'\n", + " 'Jonatan\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'title\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'The\\n'\n", + " 'Marathon\\n'\n", + " '2\\n'\n", + " ':\\n'\n", + " 'A\\n'\n", + " 'Navigation\\n'\n", + " 'System\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'booktitle\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " '2020\\n'\n", + " 'IEEE/RSJ\\n'\n", + " 'International\\n'\n", + " 'Conference\\n'\n", + " 'on\\n'\n", + " 'Intelligent\\n'\n", + " 'Robots\\n'\n", + " 'and\\n'\n", + " 'Systems\\n'\n", + " '(\\n'\n", + " 'IROS\\n'\n", + " ')}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'year\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " '2020\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'IROS 2020 talk on Nav2 Marathon Experiments:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '@article\\n'\n", + " '{\\n'\n", + " 'macenski2023survey,\\n'\n", + " '\\n'\n", + " 'title\\n'\n", + " '={\\n'\n", + " 'From\\n'\n", + " 'the\\n'\n", + " 'desks\\n'\n", + " 'of\\n'\n", + " 'ROS\\n'\n", + " 'maintainers:\\n'\n", + " 'A\\n'\n", + " 'survey\\n'\n", + " 'of\\n'\n", + " 'modern\\n'\n", + " '&\\n'\n", + " 'capable\\n'\n", + " 'mobile\\n'\n", + " 'robotics\\n'\n", + " 'algorithms\\n'\n", + " 'in\\n'\n", + " 'the\\n'\n", + " 'robot\\n'\n", + " 'operating\\n'\n", + " 'system\\n'\n", + " '2\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'author\\n'\n", + " '={\\n'\n", + " 'S.\\n'\n", + " 'Macenski,\\n'\n", + " 'T.\\n'\n", + " 'Moore,\\n'\n", + " 'DV\\n'\n", + " 'Lu,\\n'\n", + " 'A.\\n'\n", + " 'Merzlyakov,\\n'\n", + " 'M.\\n'\n", + " 'Ferguson\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'year\\n'\n", + " '={\\n'\n", + " '2023\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'journal\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'Robotics\\n'\n", + " 'and\\n'\n", + " 'Autonomous\\n'\n", + " 'Systems\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'S. Macenski, T. Moore, DV Lu, A. Merzlyakov, M. Ferguson,From '\n", + " 'the desks of ROS maintainers: A survey of modern & capable '\n", + " 'mobile robotics algorithms in the robot operating system 2,\\n'\n", + " 'Robotics and Autonomous Systems, 2023',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '@article\\n'\n", + " '{\\n'\n", + " 'macenski2024smac,\\n'\n", + " '\\n'\n", + " 'title\\n'\n", + " '={\\n'\n", + " 'Open-Source,\\n'\n", + " 'Cost-Aware\\n'\n", + " 'Kinematically\\n'\n", + " 'Feasible\\n'\n", + " 'Planning\\n'\n", + " 'for\\n'\n", + " 'Mobile\\n'\n", + " 'and\\n'\n", + " 'Surface\\n'\n", + " 'Robotics\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'author\\n'\n", + " '={\\n'\n", + " 'Steve\\n'\n", + " 'Macenski\\n'\n", + " 'and\\n'\n", + " 'Matthew\\n'\n", + " 'Booker\\n'\n", + " 'and\\n'\n", + " 'Josh\\n'\n", + " 'Wallace\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'year\\n'\n", + " '={\\n'\n", + " '2024\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'journal\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'Arxiv\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'S. Macenski, M. Booker, J. Wallace,Open-Source, Cost-Aware '\n", + " 'Kinematically Feasible Planning for Mobile and Surface Robotics,',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '@article\\n'\n", + " '{\\n'\n", + " 'macenski2023regulated,\\n'\n", + " '\\n'\n", + " 'title\\n'\n", + " '={\\n'\n", + " 'Regulated\\n'\n", + " 'Pure\\n'\n", + " 'Pursuit\\n'\n", + " 'for\\n'\n", + " 'Robot\\n'\n", + " 'Path\\n'\n", + " 'Tracking\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'author\\n'\n", + " '={\\n'\n", + " 'Steve\\n'\n", + " 'Macenski\\n'\n", + " 'and\\n'\n", + " 'Shrijit\\n'\n", + " 'Singh\\n'\n", + " 'and\\n'\n", + " 'Francisco\\n'\n", + " 'Martin\\n'\n", + " 'and\\n'\n", + " 'Jonatan\\n'\n", + " 'Gines\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'year\\n'\n", + " '={\\n'\n", + " '2023\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'journal\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'Autonomous\\n'\n", + " 'Robots\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'S. Macenski, S. Singh, F. Martin, J. Gines,Regulated Pure '\n", + " 'Pursuit for Robot Path Tracking,\\n'\n", + " 'Autonomous Robots, 2023.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '@InProceedings\\n'\n", + " '{\\n'\n", + " 'vslamComparison2021,\\n'\n", + " '\\n'\n", + " 'author\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'Merzlyakov,\\n'\n", + " 'Alexey\\n'\n", + " 'and\\n'\n", + " 'Macenski,\\n'\n", + " 'Steven\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'title\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " 'A\\n'\n", + " 'Comparison\\n'\n", + " 'of\\n'\n", + " 'Modern\\n'\n", + " 'General-Purpose\\n'\n", + " 'Visual\\n'\n", + " 'SLAM\\n'\n", + " 'Approaches\\n'\n", + " '}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'booktitle\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " '2021\\n'\n", + " 'IEEE/RSJ\\n'\n", + " 'International\\n'\n", + " 'Conference\\n'\n", + " 'on\\n'\n", + " 'Intelligent\\n'\n", + " 'Robots\\n'\n", + " 'and\\n'\n", + " 'Systems\\n'\n", + " '(\\n'\n", + " 'IROS\\n'\n", + " ')}\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'year\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " '2021\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'A. Merzlyakov, S. Macenski.A Comparison of Modern '\n", + " 'General-Purpose Visual SLAM Approaches.\\n'\n", + " 'IEEE/RSJ International Conference on Intelligent Robots and '\n", + " 'Systems (IROS), 2021.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigate To Pose and Pause Near Goal-Obstacle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'In conclusion, this particular BT would serve, both as an '\n", + " 'example and ready-to-use BT for an organizational specific '\n", + " 'application, that wishes to optimize its process cycle time.',\n", + " 'filename': 'FollowPath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Roadmaps\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Jazzy Roadmap\n", + "\n", + "\n", + "## Iron Roadmap\n", + "\n", + "\n", + "## Humble Roadmap\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Binary Filter Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"binary_filter\"\\n'\n", + " ']\\n'\n", + " '...\\n'\n", + " 'binary_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::BinaryFilter\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'default_state\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'binary_state_topic\\n'\n", + " ':\\n'\n", + " '\"/binary_state\"\\n'\n", + " 'flip_threshold\\n'\n", + " ':\\n'\n", + " '50.0',\n", + " 'context': 'Threshold for binary state flipping. Filter values higher than '\n", + " 'this threshold, will set binary state to non-default.',\n", + " 'filename': '',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: TwirlingCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": TwirlingCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Detailed Behavior Tree Walkthrough\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document serves as a reference guide to the main behavior tree (BT) used in Nav2.\n", + "There are many example behavior trees provided innav2_bt_navigator/behavior_trees,\n", + "but these sometimes have to be re-configured based on the application of the robot.\n", + "The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail.\n", + "\n", + "## Prerequisites\n", + "\n", + "\n", + "## Navigate To Pose With Replanning and Recovery\n", + "The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml.\n", + "This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions.\n", + "BTs are primarily defined in XML. The tree shown above is represented in XML as follows.\n", + "This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time.\n", + "These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree.\n", + "This can be represented in the following way:\n", + "TheNavigationsubtree mainly involves actual navigation behavior:\n", + "TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally.\n", + "The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail\n", + "(path calculation or path following), contextual recoveries will be attempted.\n", + "If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE.\n", + "The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures.\n", + "This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6).\n", + "\n", + "## Navigation Subtree\n", + "Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree.\n", + "The XML of this subtree is as follows:\n", + "This subtree has two primary actionsComputePathToPoseandFollowPath.\n", + "If either of these two actions fail, they will attempt to clear the failure contextually.\n", + "The crux of the tree can be represented with only one parent and two children nodes like this:\n", + "The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked.\n", + "While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around.\n", + "Both theComputePathToPoseand theFollowPathfollow the same general structure.\n", + "The below is theComputePathToPosesubtree:\n", + "The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree.\n", + "The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap.\n", + "Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries.\n", + "The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below:\n", + "\n", + "## Recovery Subtree\n", + "TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree.\n", + "In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient).\n", + "And the XML snippet:\n", + "The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received.\n", + "If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries.\n", + "This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”.\n", + "These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree\n", + "in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge).\n", + "If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are:\n", + "UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree.\n", + "If this renavigation was not successful, the next child of theRoundRobinwill be ticked.\n", + "For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE:\n", + "(for the sake of this example, let’s assume that the goal is never updated).\n", + "If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure).\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'BTs are primarily defined in XML. The tree shown above is '\n", + " 'represented in XML as follows.',\n", + " 'filename': 'navigate_to_pose_w_replanning_and_recovery.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'This happens until thenumber_of_retriesfor the '\n", + " 'parentRecoveryNodeis exceeded (which by default is 6).',\n", + " 'filename': 'RecoveryNode',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The XML of this subtree is as follows:',\n", + " 'filename': 'Recovery',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'And the XML snippet:',\n", + " 'filename': 'Navigation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Container Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Creating Dev Containers\n", + "Before creating a dev container, you’ll want to choose the exact configuration to use. By default the.devcontainer/devcontainer.jsonconfiguration is selected, however you can also choose any otherdevcontainer.jsonfile in the.devcontainer/directory, where such configurations can be nested to provide greater customization: either by targeting different stages within different Dockerfiles, overriding any merged metadata or default properties, or inclusion of additional extensions and alternate commands.\n", + "\n", + "## Building the image\n", + "When first creating Dev Containers, any supporting tool or service used will download and build the docker images needed to run the container. This includes pulling any parent images the project’s Dockerfile buildsFROM, as well as any tags or layers declared viacacheFrom, as specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until such layers are updated and pushed to the image registry.\n", + "Specifically, for this project, the defaultdevcontainer.jsonfile targets thedeverstage within the project’s root Dockerfile, the stage that also includes handy tools for developing the project, such as bash auto completion. This stage is in turn builtFROMthebuilderstage, the stage that only includes the dependencies needed for building the project, as reused by the project’s CI. For example, thedeverstage modifies/etc/bash.bashrcto automatically sourceinstall/setup.bashfrom the underlay workspace, ensuring all VS Code extensions are loaded with the correct environment, while avoiding any race conditions during installation and startup.\n", + "To speed up the initial build, images layers from thisbuilderstage are cached by pulling the same image tag used by the project’s CI, hosted from the image registry. This ensures your local dev container replicates our CI environment as close as possible, while benefiting from any cached work preemptively performed by the CI. Yet, this still allows you to customize the project’s Dockerfile and rebuild the container, without needing to update CI images to reflect your local modifications.\n", + "Once the base image from the target stage is built, the supporting tool or service may then add additional layers to the image, such as installing additionalfeaturesor customizations. For VS Code, this also includes some fancy file caching for any extensions to install later. Once this custom image is built, it is then used to start the dev container.\n", + "\n", + "## Starting the container\n", + "When first creating Dev Containers, any supporting tool or service will invoke a sequence of commands specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until the container is rebuilt, triggered by either updating the Dockerfile, base image, or.devcontainer/config.\n", + "Specifically, for this project, the defaultdevcontainer.jsonconfig executes theonCreateCommandto initially colcon cache, clean, and build the overlay workspace for the project. This ensures the workspace is precompiled and ready to use, while also ensuring any changes to the project’s source code are reflected in the container. This is useful for:\n", + "While the colcon workspace is being built, VS Code will simultaneously install any specified extensions and settings. Next theupdateContentCommandis executed, which reruns whenever the container is started or restarted. Specifically, for this project, this command re-cleans and re-builds the same colcon workspace as before, but only for invalidated packages detected by colcon cache using the lockfiles initialized during theonCreateCommand. This caching behavior also replicates the project’s CI workflow. This is useful for:\n", + "Finally, thepostCreateCommandis executed, which also reruns whenever the container is started or restarted. Specifically, for this project, this command makes a last few tweaks to the user’s environment to improve the development experience.\n", + "To speed up subsequent startups, volumes that are mounted to the container store a persistent ccache and colcon workspace, while the environment is set to enableccacheviacolcon mixins. These volumes are labeled using thedevcontainerIdvariable, which uniquely identify the dev container on a Docker host, allowing us to refer to a common identifier that is unique to the dev container, while remaining stable across rebuilds. This is useful for:\n", + "Additionally, the container can be grantedprivilegedand non-defaultLinux capabilities, connected using thehostnetwork mode andIPCandPIDspaces, with a relaxedsecurity configurationand seccomp confinement for native debugging and external connectivity. This is useful for:\n", + "\n", + "## Using Dev Containers\n", + "Once the dev container has been created and setup completed, VS Code will open a new workspace directly from the project’s root directory, which itself is mounted within the source directory in the overlay colcon workspace. From here you can build, test, and debug the project as you normally would, with the added benefit of having the project’s dependencies, intellisense, linters, and other extensions pre-configured and ready to use. Simply open a new terminal (Crtl+Shift+`), cd to the root of the colcon workspace, and run the usual colcon commands.\n", + "\n", + "## Terminals\n", + "If you prefer using an alternate terminal emulator, rather than the built-in VS Code terminal, you can open a separate shell session by simply using the Dev Container CLI or directly using the Docker CLI via theexecsubcommands.\n", + "\n", + "## Lifecycle\n", + "While using the dev container, try and keep in mind the lifecycle of the container itself. Specifically, containers are ephemeral, meaning they are normally destroyed and recreated whenever the dev environment is rebuilt or updated. Subsequently, a best practice is to avoid storing any persistent data within the container, and instead utilize the project’s source directory, or a separate mounted volume. When altering the development environment inside the container, try to remember to codify your changes into the Dockerfile, or thedevcontainer.jsonconfig file, so that they can be easily reproduced and shared with others.\n", + "\n", + "## Rebuilding\n", + "From time to time, you may need to rebuild the dev container, either because the base image, or.devcontainer/config was updated, or simply out of wanting a new fresh development environment. To do so, simply open the Command Palette (Ctrl+Shift+P) and select theRemote-Containers:RebuildContainercommand.\n", + "For example, you may need to rebuild the dev container when:\n", + "When necessary, you can also rebuild the container from scratch, e.i. without caching from docker, by selecting theRemote-Containers:RebuildContainerWithoutCachecommand. This instead omits the--cache-fromflag from thedockerbuildxcommand, while also adding the--no-cacheand--pullflags to prevent caching from any existing image layers, using only the latest images from a container registry.\n", + "Rebuilding without caching may be necessary when:\n", + "Specifically, for this project, volumes remain unaffected by this rebuilding process: i.e. those used to mount the ccache directory or colcon workspace. While volume management is left to the user’s discretion, other projects may of course handle this differently, so be sure to check the./devcontainerconfiguration to inspect how various container resources may be managed.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'find\\n'\n", + " '/tmp\\n'\n", + " '-type\\n'\n", + " 'f\\n'\n", + " '-path\\n'\n", + " '\"*/devcontainers-*/env-loginInteractiveShell.json\"\\n'\n", + " '-exec\\n'\n", + " '\\\\\\n'\n", + " 'jq\\n'\n", + " '-r\\n'\n", + " '\\'to_entries | .[] | \"\\\\(.key)=\\\\(.value | @sh)\"\\'\\n'\n", + " '{}\\n'\n", + " '\\\\;\\n'\n", + " '>\\n'\n", + " '.env\\n'\n", + " '\\n'\n", + " 'source\\n'\n", + " '.env\\n',\n", + " 'context': 'The environment provided byuserEnvProbecan be sourced manually. '\n", + " 'E.g. for the defaultloginInteractiveShellprobe:',\n", + " 'filename': 'loginInteractiveShell',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GoalUpdater\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The resulting updated goal. If no goal received by subscription, '\n", + " 'it will be the input_goal',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Planner and Controller Servers\n", + "Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice.\n", + "The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment.\n", + "The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station.\n", + "As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server.\n", + "\n", + "## Selecting the Algorithm Plugins\n", + "In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server.\n", + "\n", + "## Planner Server\n", + "The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility.\n", + "As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments.\n", + "One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots.\n", + "Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds.\n", + "There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration.\n", + "\n", + "## Summary\n", + "\n", + "\n", + "## Example Configuration\n", + "An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Controller Server\n", + "The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity.\n", + "TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint.\n", + "Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots.\n", + "Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots.\n", + "The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots.\n", + "\n", + "## Summary\n", + "All of these algorithms work for both circular and non-circular robots.\n", + "\n", + "## Example Configuration\n", + "Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Non-circular Differential, Non-circular Omnidirectional',\n", + " 'filename': 'SmacLatticeplanner',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'All of these algorithms work for both circular and non-circular '\n", + " 'robots.',\n", + " 'filename': 'TrajectoryGenerationplugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Costmap 2D\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Costmap2D ROS Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thepluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Plugin Parameters\n", + "\n", + "\n", + "## Costmap Filters Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ',\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'footprint_padding\\n'\n", + " ':\\n'\n", + " '0.03\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '# radius set and used, so no footprint points\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " '# no frame set, uses frame from message\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"PointCloud2\"\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'subscribe_to_updates\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'inflate_unknown\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'inflate_around_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': '“nav2_costmap_2d::InflationLayer”',\n", + " 'filename': 'plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PathAlignCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": PathAlignCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: DWB Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Controller\n", + "\n", + "\n", + "## Plugins\n", + "The plugins listed below are inside thedwb_pluginsnamespace.\n", + "\n", + "## Trajectory Critics\n", + "The trajectory critics listed below are inside thedwb_criticsnamespace.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# controller server parameters (see Controller Server for more '\n", + " 'info)\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# DWB controller parameters\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'debug_trajectory_details\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'min_vel_x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'min_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'max_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_theta\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_speed_xy\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_speed_xy\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'min_speed_theta\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_x\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'acc_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_theta\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'decel_lim_x\\n'\n", + " ':\\n'\n", + " '-2.5\\n'\n", + " 'decel_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'decel_lim_theta\\n'\n", + " ':\\n'\n", + " '-3.2\\n'\n", + " 'vx_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'vy_samples\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'vtheta_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'sim_time\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'linear_granularity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'angular_granularity\\n'\n", + " ':\\n'\n", + " '0.025\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'trans_stopped_velocity\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'short_circuit_trajectory_evaluation\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'limit_vel_cmd_in_traj\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"RotateToGoal\"\\n'\n", + " ',\\n'\n", + " '\"Oscillation\"\\n'\n", + " ',\\n'\n", + " '\"BaseObstacle\"\\n'\n", + " ',\\n'\n", + " '\"GoalAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathDist\"\\n'\n", + " ',\\n'\n", + " '\"GoalDist\"\\n'\n", + " ']\\n'\n", + " 'BaseObstacle.scale\\n'\n", + " ':\\n'\n", + " '0.02\\n'\n", + " 'PathAlign.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalAlign.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'PathAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'GoalAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'PathDist.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalDist.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'RotateToGoal.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'RotateToGoal.slowing_factor\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'RotateToGoal.lookahead_time\\n'\n", + " ':\\n'\n", + " '-1.0',\n", + " 'context': 'The trajectory critics listed below are inside '\n", + " 'thedwb_criticsnamespace.',\n", + " 'filename': 'dwb_critics',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GoalReached\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameter\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# other bt_navigator parameters\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'goal_reached_tol\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Tolerance of accepting pose as the goal (m).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'Robot base frame.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: CancelAssistedTeleop\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'assisted_teleop',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: About and Contact\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## About\n", + "Navigation is a community effort to lower the barrier of entry of mobile robotics technology for all.\n", + "This project is one of the flagship projects along with MoveIt that acts as an applications entry point and frameworks for ROS.\n", + "Navigation in ROS 2 builds on the wild success of the original Navigation Stack (Nav Stack) in ROS (1).\n", + "This project has been used by researchers, educators, and industry for over 10 years.\n", + "There are very few projects that have lasted as long or were as successful as ROS (1) Navigation.\n", + "We would like to thank David Lu!! and Mike Ferguson for their tireless over the span of a decade to keep the Nav Stack alive and well.\n", + "Without their hard work, this project would not have been able to happen.\n", + "For a list of robots using Navigation2, seeRobots Using.\n", + "Aslas, as time moves on, so must we.\n", + "ROS (1) had a great run and those of us that build projects using it will remember it fondly(ish).\n", + "With change comes possibilities.\n", + "Navigation2 builds on the success but redesigns the framework to be more flexible and the feedback gathered over 10 years.\n", + "We strive to create an open community and encourage new ROS users and experts alike to collaborate.\n", + "However, that can’t happen without your issues, pull requests, and support.\n", + "Navigation, like all open-source projects, is kept going by a dedicated group of developers, maintainers, users, and collaborators.\n", + "We would like to thank here our current and past contributors and maintainers.\n", + "If you or your organization are interested in sponsoring Navigation or any work around it, please reach out to the current project lead.\n", + "Our current leadership team includes:\n", + "Our former leadership team includes:\n", + "\n", + "## Contact\n", + "If you are interested in contacting someone about Navigation, ROS 2, or related projects, please email the project leader or emailinfo@opennav.org.\n", + "We intentionally make our emails easy to find.\n", + "If your inquiry relates to bugs or open-source feature requests, consider posting a ticket on our GitHub project.\n", + "If your inquiry relates to configuration support or private feature development, reach out and we may be able to connect you with\n", + "independent consultants or contractors that know this project well.\n", + "Check out the Navigation 2Slackcommunity.\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: RecoveryNode\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Number of retries.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: StandardTrajectoryGenerator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Constrained smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Smoother Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"SmoothPath\"\\n'\n", + " ']\\n'\n", + " 'SmoothPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_constrained_smoother/ConstrainedSmoother\"\\n'\n", + " 'reversing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to detect forward/reverse direction and cusps. Should be '\n", + " 'set to false for paths without orientations assigned\\n'\n", + " 'path_downsampling_factor\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '# every n-th node of the path is taken. Useful for speed-up\\n'\n", + " 'path_upsampling_factor\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " '# 0 - path remains downsampled, 1 - path is upsampled back to '\n", + " 'original granularity using cubic bezier, 2... - more upsampling\\n'\n", + " 'keep_start_orientation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to prevent the start orientation from being smoothed\\n'\n", + " 'keep_goal_orientation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to prevent the gpal orientation from being smoothed\\n'\n", + " 'minimum_turning_radius\\n'\n", + " ':\\n'\n", + " '0.40\\n'\n", + " '# minimum turning radius the robot can perform. Can be set to 0.0 '\n", + " '(or w_curve can be set to 0.0 with the same effect) for '\n", + " 'diff-drive/holonomic robots\\n'\n", + " 'w_curve\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# weight to enforce minimum_turning_radius\\n'\n", + " 'w_dist\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '# weight to bind path to original as optional replacement for cost '\n", + " 'weight\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '2000000.0\\n'\n", + " '# weight to maximize smoothness of path\\n'\n", + " 'w_cost\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " '# weight to steer robot away from collision and cost\\n'\n", + " '# Parameters used to improve obstacle avoidance near cusps '\n", + " '(forward/reverse movement changes)\\n'\n", + " 'w_cost_cusp_multiplier\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '# option to use higher weight during forward/reverse direction '\n", + " 'change which is often accompanied with dangerous rotations\\n'\n", + " 'cusp_zone_length\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '# length of the section around cusp in which nodes use '\n", + " 'w_cost_cusp_multiplier (w_cost rises gradually inside the zone '\n", + " 'towards the cusp point, whose costmap weight eqals '\n", + " 'w_cost*w_cost_cusp_multiplier)\\n'\n", + " '# Points in robot frame to grab costmap values from. Format: [x1, '\n", + " 'y1, weight1, x2, y2, weight2, ...]\\n'\n", + " '# IMPORTANT: Requires much higher number of iterations to actually '\n", + " 'improve the path. Uncomment only if you really need it (highly '\n", + " 'elongated/asymmetric robots)\\n'\n", + " '# cost_check_points: [-0.185, 0.0, 1.0]\\n'\n", + " 'optimizer\\n'\n", + " ':\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '70\\n'\n", + " '# max iterations of smoother\\n'\n", + " 'debug_optimizer\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# print debug info\\n'\n", + " 'gradient_tol\\n'\n", + " ':\\n'\n", + " '5e3\\n'\n", + " 'fn_tol\\n'\n", + " ':\\n'\n", + " '1.0e-15\\n'\n", + " 'param_tol\\n'\n", + " ':\\n'\n", + " '1.0e-20',\n", + " 'context': 'Parameter tolerance optimization termination criterion',\n", + " 'filename': 'DENSE_QR',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Transformations\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Transforms Introduction\n", + "Many ROS packages require the transform tree of a robot to be published using the TF2 ROS package. A transformation tree defines the relations between different coordinate systems, in terms of translation, rotation, and relative motion. To make this more concrete, let us apply an example of a simple robot that has a mobile base with a single laser sensor mounted on top of it.\n", + "This robot has two defined coordinate frames: one corresponding to the center point of the mobile base of the robot, and one for the center point of the laser that is mounted on top of the base. We’ll call the coordinate frame attached to the mobile basebase_linkand we’ll call the coordinate frame attached to the laserbase_laser. Note that will be talking more about the naming and conventions of these coordinate frames in the next section.\n", + "At this point, let’s assume that we have some data from the laser in the form of distance measurements from the laser’s center point. In other words, we have some data in thebase_lasercoordinate frame.\n", + "Now, suppose we want to take this data and use it to help the mobile base avoid obstacles in the world. To do this successfully, we need a way to transform the laser scan we’ve received from thebase_laserframe to thebase_linkframe. In essence, we need to define a relationship between thebase_laserandbase_linkcoordinate frames.\n", + "In defining this relationship, let us assume that the only data we have is that the laser is mounted 10cm forward and 20cm above the center point of the mobile base. This gives us a translational offset that relates thebase_linkframe to thebase_laserframe. Specifically, we know that to get data from thebase_linkframe to thebase_laserframe, we must apply a translation of (x: 0.1m, y: 0.0m, z: 0.2m), and transversely, to get data from thebase_laserframe to thebase_linkframe, we must apply the opposite translation (x: -0.1m, y: 0.0m, z: -0.20m).\n", + "We could choose to manage this relationship ourselves, meaning to store and apply the appropriate translations between the frames when necessary, but this becomes a real pain as the number of coordinate frames increases. Luckily, we don’t have to do this work ourselves. Instead, we’ll define the relationship betweenbase_linkandbase_laseronce using TF2 and let it manage the transformation between the two coordinate frames for us. This is especially useful when working with non-static transformations, such as a set of frames that are moving relative to each other, like a robot base frame in a map frame.\n", + "To define and store the relationship between thebase_linkandbase_laserframes using TF2, we need to add them to a transform tree. Conceptually, each node in the transform tree corresponds to a coordinate frame, and each edge corresponds to the transform that needs to be applied to move from the current node to its child. TF2 uses a tree structure to guarantee that there is only a single traversal that links any two coordinate frames together, and assumes that all edges in the tree are directed from parent to child nodes.\n", + "To create a transform tree for our simple example, we’ll create two nodes: one for thebase_linkcoordinate frame and one for thebase_lasercoordinate frame. To create the edge between them, we first need to decide which node will be the parent and which will be the child. Remember — this distinction is important because TF2 assumes that all transforms move from parent to child.\n", + "Let’s choose thebase_linkcoordinate frame as the parent because when other pieces/sensors are added to the robot, it will make the most sense for them to relate to thebase_laserframe by traversing through thebase_linkframe. This means that the transform associated with the edge connectingbase_linkandbase_lasershould be (x: 0.1m, y: 0.0m, z: 0.2m).\n", + "With this transform tree set up, converting the laser scan received in thebase_laserframe to thebase_linkframe is as simple as making a call to the TF2 library. Our robot can now use this information to reason about laser scans in thebase_linkframe and safely plan around obstacles in its environment.\n", + "\n", + "## Static Transform Publisher Demo\n", + "Now let’s try publishing a very simple transform using the static_transform_publisher tool provided by TF2. We will be publishing a transformation from the linkbase_linkto the linkbase_laserwith a translation of (x: 0.1m, y: 0.0m, z: 0.2m). Note that we will be building the transform from the diagram earlier in this tutorial.\n", + "Open up your command line and execute the following command:\n", + "With this, we are now successfully publishing ourbase_linktobase_lasertransform in TF2. Let us now check if it is working properly throughtf2_echo. Open up a separate command line window and execute the following:\n", + "You should be able to observe a repeated output similar to the one below.\n", + "And that’s it for this short demo - we were able to successfully publish a transform frombase_linktobase_laserusing the TF2 library. Note that we do not recommend using the above demo in publishing transforms for your actual robotics projects, it is just a quick demo to see TF2 in action. For a real robot system, we would create a URDF file which embeds this information and more about your robot for use of the robot_state_publisher rather than the static_transform_publisher. There are more suitable and practical ways to go about this which will be discussed in theSetting Up The URDFtutorial.\n", + "\n", + "## Transforms in Navigation2\n", + "There are two important ROS REPs which we highly suggest for you to check out. These documents detail some standards set about by the ROS community to ensure proper operation across different packages. Nav2 also adheres to these standards and conventions.\n", + "To quickly summarize REP 105, this document specifies the naming conventions and semantic meanings of the different coordinate frames used in ROS. Of interest to this tutorial are thebase_link,odomandmapcoordinate frames. Thebase_linkis a coordinate frame that is attached to a fixed position on the robot, typically at its main chassis and its rotational center. Theodomcoordinate frame is a fixed frame relative to the robot’s starting position and is mainly used for locally-consistent representations of distances. Lastly, themapcoordinate frame is a world fixed frame that is used for globally-consistent representations of distances.\n", + "REP 103, on the other hand, discusses some standard units of measure and other related conventions to keep integration issues between different ROS packages to a minimum. The basic overview is that frames are defined using the right hand rule, with Z up and X forward, and units should be standard SI units.\n", + "Now let’s move on to some specifics for the Navigation2 package to function correctly. Nav2 requires the following transformations to be published in ROS:\n", + "The first transformmap=>odomis usually provided by a different ROS package dealing with localization and mapping such as AMCL. This transform updates live in use so we don’t set static values for this in our robot’s TF tree. Further detail about how to set this up may be pretty complex, so we highly suggest to have a look at the documentation of the mapping or localization package you are using for your platform. All ROS compliant SLAM and localization packages will provide you with this transformation automatically on launch.\n", + "Theodom=>base_linkis usually published by our odometry system using sensors such as wheel encoders. This is typically computed via sensor fusion of odometry sensors (IMU, wheel encoders, VIO, etc) using therobot_localizationpackage.\n", + "All other statically defined transforms (e.g.base_link=>base_laser,base_link=>wheels,wheels=>IMU, etc) is what we will be talking about for the rest of this guide. This transformation tree is used by Nav2 to properly relate the information from sensors or other frame of interest to the rest of the robot. The transformation between these two coordinate frames is usually provided to Nav2 through the Robot State Publisher and the Universal Robot Descriptor File (URDF). In cases where there are more sensor coordinate frames on your platform, then a transform tree frombase_linkto each sensor coordinate frame needs to be published.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed about the concept of transforms and how they are used in Nav2.\n", + "In the last section, we have also explored using the static_transform_publisher of TF2 to publish our transforms. You may use this to set up your transforms for Nav2, but this is generally not the best way to do it. In most robotics projects, we make use of the Robot State Publisher since it is much easier to use and scales well as our robot gets more complex. We will be talking about the Robot State Publisher, URDF, and how to set it up in the next tutorial onSetting Up The URDF.\n", + "Lastly, we also discussed the three published transform requirements of Nav2 and the necessary REPs to keep in mind when setting them up.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '.1\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '.2\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'base_link\\n'\n", + " 'base_laser\\n',\n", + " 'context': 'Open up your command line and execute the following command:',\n", + " 'filename': 'base_laser',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nbase_link\\nbase_laser\\n',\n", + " 'context': 'With this, we are now successfully publishing '\n", + " 'ourbase_linktobase_lasertransform in TF2. Let us now check if it '\n", + " 'is working properly throughtf2_echo. Open up a separate command '\n", + " 'line window and execute the following:',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '0\\n'\n", + " '.0\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.100,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.200\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '1\\n'\n", + " '.000\\n'\n", + " ']',\n", + " 'context': 'You should be able to observe a repeated output similar to the '\n", + " 'one below.',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Map Server / Saver\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Map Saver Parameters\n", + "\n", + "\n", + "## Map Server Parameters\n", + "\n", + "\n", + "## Costmap Filter Info Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'map_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"turtlebot3_world.yaml\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'map_saver\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'save_map_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'free_thresh_default\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'occupied_thresh_default\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'filter_space_value=base+multiplier*mask_value',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Wait\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Action server timeout (ms).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: LimitedAccelGenerator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DistanceController\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Robot base frame.',\n", + " 'filename': 'GoalReached',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Tree XML Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Plugins\n", + "\n", + "\n", + "## Condition Plugins\n", + "\n", + "\n", + "## Control Plugins\n", + "\n", + "\n", + "## Decorator Plugins\n", + "\n", + "\n", + "## Example\n", + "This Behavior Tree replans the global path periodically at 1 Hz and it also has\n", + "recovery actions.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This Behavior Tree replans the global path periodically at 1 Hz '\n", + " 'and it also has\\n'\n", + " 'recovery actions.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigate To Pose With Consistent Replanning And If Path Becomes Invalid\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'While this behavior tree does not make use of it, '\n", + " 'thePlannerSelector,ControllerSelector, '\n", + " 'andGoalCheckerSelectorbehavior tree nodes can also be helpful. '\n", + " 'Rather than hardcoding the algorithm to use '\n", + " '(GridBasedandFollowPath), these behavior tree nodes will allow a '\n", + " 'user to dynamically change the algorithm used in the navigation '\n", + " 'system via a ROS topic. It may be instead advisable to create '\n", + " 'different subtree contexts using condition nodes with specified '\n", + " 'algorithms in their most useful and unique situations. However, '\n", + " 'the selector nodes can be a useful way to change algorithms from '\n", + " 'an external application rather than via internal behavior tree '\n", + " 'control flow logic. It is better to implement changes through '\n", + " 'behavior tree methods, but we understand that many professional '\n", + " 'users have external applications to dynamically change settings '\n", + " 'of their navigators.',\n", + " 'filename': 'FollowPath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Commander API\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage.\n", + "A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults).\n", + "You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints().\n", + "\n", + "## Commander API\n", + "The methods provided by the basic navigator are shown below, with inputs and expected returns.\n", + "If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype.\n", + "New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches.\n", + "\n", + "## Costmap API\n", + "This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API.\n", + "\n", + "## Footprint Collision Checker API\n", + "This is a Python3 API for a Footprint Collision Checker.\n", + "It provides the needed methods to manipulate the coordinates\n", + "and calculate the cost of a Footprint in a given map.\n", + "\n", + "## Examples and Demos\n", + "All of these can be found in thepackage.\n", + "Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user:\n", + "Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'from\\n'\n", + " 'nav2_simple_commander.robot_navigator\\n'\n", + " 'import\\n'\n", + " 'BasicNavigator\\n'\n", + " 'import\\n'\n", + " 'rclpy\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'nav\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ')\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# if autostarted, else use lifecycleStartup()\\n'\n", + " '# ...\\n'\n", + " 'path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getPath\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ',\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'smoothed_path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'smoothPath\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_duration\\n'\n", + " '>\\n'\n", + " '600\\n'\n", + " ':\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'cancelTask\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'You may use this simple commander preempt commands of the same '\n", + " 'type (e.g. you can preempt agoToPose()with anothergoToPose()) '\n", + " 'but you must explicitly cancel a current command and issue a new '\n", + " 'one if switching betweengoToPose(),goThroughPoses(), '\n", + " 'orfollowWaypoints().',\n", + " 'filename': 'followWaypoints()',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Controller Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugins\n", + "When theprogress_checker_plugins,goal_checker_pluginorcontroller_pluginsparameters are not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'failure_tolerance\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " '# goal_checker_plugin: \"goal_checker\" For Galactic and older\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': '“dwb_core::DWBLocalPlanner”',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Simple Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'max_its\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " 'w_data\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '0.3',\n", + " 'context': 'Weight to apply to smooth the path (smooths it)',\n", + " 'filename': '>=1',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Costmap 2D\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Costmap2D ROS Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thepluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Plugin Parameters\n", + "\n", + "\n", + "## Costmap Filters Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ',\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'footprint_padding\\n'\n", + " ':\\n'\n", + " '0.03\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '# radius set and used, so no footprint points\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " '# no frame set, uses frame from message\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"PointCloud2\"\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'subscribe_to_updates\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'inflate_unknown\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'inflate_around_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': '“nav2_costmap_2d::InflationLayer”',\n", + " 'filename': 'plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create you own Behavior Plugin.\n", + "The Behavior Plugins live in the behavior server.\n", + "Unlike the planner and controller servers, each behavior will host its own unique action server.\n", + "The planners and controllers have the same API as they accomplish the same task.\n", + "However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server.\n", + "This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Behavior Plugin\n", + "We will create a simple send sms behavior.\n", + "It will use Twilio to send a message via SMS to a remote operations center.\n", + "The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior.\n", + "This package can be a considered as a reference for writing Behavior Plugin.\n", + "Our example plugin implements the plugin class ofnav2_core::Behavior.\n", + "However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead.\n", + "This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required.\n", + "The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin.\n", + "The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface.\n", + "Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper.\n", + "For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement.\n", + "This tutorial uses this wrapper so these are the main elements we will address.\n", + "For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters.\n", + "In recoveries,onRun()method must set any initial state and kick off the behavior.\n", + "For the case of our call for help behavior, we can trivially compute all of our needs in this method.\n", + "We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership.\n", + "This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center.\n", + "We use the service Twilio to complete this task.\n", + "Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number).\n", + "You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations.\n", + "We use the_twilioobject to send our message with your account information from the configuration file.\n", + "We send the message and log to screen whether or not the message was sent successfully or not.\n", + "We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client.\n", + "onCycleUpdate()is trivially simple as a result of our short-running behavior.\n", + "If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values.\n", + "For our example, we simply return success because we already completed our mission inonRun().\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "\n", + "## 2- Exporting the Behavior Plugin\n", + "Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name.\n", + "We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account.\n", + "\n", + "## 4- Run Behavior Plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "In a new terminal run:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Status\\n'\n", + " 'SendSms::onRun\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'const\\n'\n", + " 'Action\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '>\\n'\n", + " 'command\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'response\\n'\n", + " ';\\n'\n", + " 'bool\\n'\n", + " 'message_success\\n'\n", + " '=\\n'\n", + " '_twilio\\n'\n", + " '->\\n'\n", + " 'send_message\\n'\n", + " '(\\n'\n", + " '_to_number\\n'\n", + " ',\\n'\n", + " '_from_number\\n'\n", + " ',\\n'\n", + " 'command\\n'\n", + " '->\\n'\n", + " 'message\\n'\n", + " ',\\n'\n", + " 'response\\n'\n", + " ',\\n'\n", + " '\"\"\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'message_success\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS send failed.\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'FAILED\\n'\n", + " '};\\n'\n", + " '}\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"SMS sent successfully!\"\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'ResultStatus\\n'\n", + " '{\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " '};\\n'\n", + " '}',\n", + " 'context': 'In recoveries,onRun()method must set any initial state and kick '\n", + " 'off the behavior.\\n'\n", + " 'For the case of our call for help behavior, we can trivially '\n", + " 'compute all of our needs in this method.',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': 'Status\\n'\n", + " 'SendSms::onCycleUpdate\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'Status\\n'\n", + " '::\\n'\n", + " 'SUCCEEDED\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'onCycleUpdate()is trivially simple as a result of our '\n", + " 'short-running behavior.\\n'\n", + " 'If the behavior was instead longer running like spinning, '\n", + " 'navigating to a safe area, or getting out of a bad spot and '\n", + " 'waiting for help, then this function would be checking for '\n", + " 'timeouts or computing control values.\\n'\n", + " 'For our example, we simply return success because we already '\n", + " 'completed our mission inonRun().',\n", + " 'filename': 'onRun()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_sms_bahavior\\n'\n", + " '::\\n'\n", + " 'SendSms\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Behavior\\n'\n", + " ')',\n", + " 'context': 'To export the behavior, we need to provide two lines',\n", + " 'filename': 'nav2_core::Behavior',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'an\\n'\n", + " 'SMS\\n'\n", + " 'text\\n'\n", + " 'message\\n'\n", + " 'recovery.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'behavior_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and later\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Humble and later\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below to replace following params',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " '# Humble and newer\\n'\n", + " 'recoveries_server\\n'\n", + " ':\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Humble and newer\\n'\n", + " 'recovery_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"send_sms\"\\n'\n", + " ']\\n'\n", + " '# Galactic and earlier\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'send_sms\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_sms_behavior::SendSms\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'account_sid\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your sid\\n'\n", + " 'auth_token\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your token\\n'\n", + " 'from_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# your number\\n'\n", + " 'to_number\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " '# the operations center number\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2',\n", + " 'context': 'with',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'action\\n'\n", + " 'send_goal\\n'\n", + " '\"send_sms\"\\n'\n", + " 'nav2_sms_behavior/action/SendSms\\n'\n", + " '\"{message : Hello!! Navigation2 World }\"',\n", + " 'context': 'In a new terminal run:',\n", + " 'filename': 'SendSms',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with a Physical Turtlebot 3\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "This tutorial may take about 1 hour to complete.\n", + "It depends on your experience with ROS, robots, and what computer system you have.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Your Environment Variables\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "\n", + "## 1- Launch Turtlebot 3\n", + "You will need to launch your robot’s interface, for example:\n", + "\n", + "## 2- Launch Nav2\n", + "You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM.\n", + "In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping.\n", + "Required files:\n", + ".yamlis the configuration file for the map we want to provide Nav2.\n", + "In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location.\n", + "You need to make sure these values are correct.\n", + "More information about the map.yaml can be foundhere.\n", + "Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes.\n", + "Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo.\n", + "ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml\n", + "Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file.\n", + "\n", + "## 3- Launch RVIZ\n", + "Launch RVIZ with a pre-defined configuration file.\n", + "Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz.\n", + "Click on the Start button (Bottom Left) if you set the auto_start parameter to false.\n", + "Then, the map should appear in RViz.\n", + "\n", + "## 4- Initialize the Location of Turtlebot 3\n", + "First, find where the robot is on the map. Check where your robot is in the room.\n", + "Set the pose of the robot in RViz.\n", + "Click on the 2D Pose Estimate button and point the location of the robot on the map.\n", + "The direction of the green arrow is the orientation of Turtlebot.\n", + "Now, the 3D model of Turtlebot should move to that location.\n", + "A small error in the estimated location is tolerable.\n", + "\n", + "## 5- Send a Goal Pose\n", + "Pick a target location for Turtlebot on the map.\n", + "You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons.\n", + "Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic.\n", + "Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map.\n", + "Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Smac State Lattice Planner\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smac_planner::SmacPlannerLattice\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'allow_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Allow traveling in unknown space\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " '# dist-to-goal heuristic cost (distance) for valid tolerance '\n", + " 'endpoints if exact goal cannot be found.\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '1000000\\n'\n", + " '# Maximum total iterations to search for before failing (in case '\n", + " 'unreachable), set to -1 to disable\\n'\n", + " 'max_on_approach_iterations\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " '# Maximum number of iterations after within tolerances to continue '\n", + " 'to try to find exact solution\\n'\n", + " 'max_planning_time\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '# Max time in s for planner to plan, smooth\\n'\n", + " 'analytic_expansion_ratio\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " '# The ratio to attempt analytic expansions during search for final '\n", + " 'approach.\\n'\n", + " 'analytic_expansion_max_length\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '# For Hybrid/Lattice nodes The maximum length of the analytic '\n", + " 'expansion to be considered valid to prevent unsafe shortcutting\\n'\n", + " 'analytic_expansion_max_cost\\n'\n", + " ':\\n'\n", + " '200.0\\n'\n", + " '# The maximum single cost for any part of an analytic expansion to '\n", + " 'contain and be valid, except when necessary on approach to goal\\n'\n", + " 'analytic_expansion_max_cost_override\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether or not to override the maximum cost setting if within '\n", + " 'critical distance to goal (ie probably required)\\n'\n", + " 'reverse_penalty\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '# Penalty to apply if motion is reversing, must be => 1\\n'\n", + " 'change_penalty\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '# Penalty to apply if motion is changing directions (L to R), must '\n", + " 'be >= 0\\n'\n", + " 'non_straight_penalty\\n'\n", + " ':\\n'\n", + " '1.05\\n'\n", + " '# Penalty to apply if motion is non-straight, must be => 1\\n'\n", + " 'cost_penalty\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '# Penalty to apply to higher cost areas when adding into the '\n", + " 'obstacle map dynamic programming distance expansion heuristic. This '\n", + " 'drives the robot more towards the center of passages. A value '\n", + " 'between 1.3 - 3.5 is reasonable.\\n'\n", + " 'rotation_penalty\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '# Penalty to apply to in-place rotations, if minimum control set '\n", + " 'contains them\\n'\n", + " 'retrospective_penalty\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'lattice_filepath\\n'\n", + " ':\\n'\n", + " '\"\"\\n'\n", + " '# The filepath to the state lattice graph\\n'\n", + " 'lookup_table_size\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " '# Size of the dubin/reeds-sheep distance window to cache, in '\n", + " 'meters.\\n'\n", + " 'cache_obstacle_heuristic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Cache the obstacle map dynamic programming distance expansion '\n", + " 'heuristic between subsequent replannings of the same goal location. '\n", + " 'Dramatically speeds up replanning performance (40x) if costmap is '\n", + " 'largely static.\\n'\n", + " 'allow_reverse_expansion\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# If true, allows the robot to use the primitives to expand in the '\n", + " \"mirrored opposite direction of the current robot's orientation (to \"\n", + " 'reverse).\\n'\n", + " 'smooth_path\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# If true, does a simple and quick smoothing post-processing to the '\n", + " 'path\\n'\n", + " 'smoother\\n'\n", + " ':\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '1000\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'w_data\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'refinement_num\\n'\n", + " ':\\n'\n", + " '2',\n", + " 'context': 'Number of times to recursively attempt to smooth, must be>=1.',\n", + " 'filename': '>=1',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Controller Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugins\n", + "When theprogress_checker_plugins,goal_checker_pluginorcontroller_pluginsparameters are not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'failure_tolerance\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " '# goal_checker_plugin: \"goal_checker\" For Galactic and older\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': '“dwb_core::DWBLocalPlanner”',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: FollowPath\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Follow path error code. SeeFollowPathaction for the enumerated '\n", + " 'set of error code definitions.',\n", + " 'filename': 'FollowPath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PoseProgressChecker\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_controller plugin name defined in theprogress_checker_plugin_idparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Related Projects\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: PathExpiringTimer\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Checks if the timer has expired. Returns success if the timer '\n", + " 'has expired, otherwise it returns failure.\\n'\n", + " 'The timer will reset if the path gets updated.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Commander API\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage.\n", + "A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults).\n", + "You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints().\n", + "\n", + "## Commander API\n", + "The methods provided by the basic navigator are shown below, with inputs and expected returns.\n", + "If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype.\n", + "New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches.\n", + "\n", + "## Costmap API\n", + "This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API.\n", + "\n", + "## Footprint Collision Checker API\n", + "This is a Python3 API for a Footprint Collision Checker.\n", + "It provides the needed methods to manipulate the coordinates\n", + "and calculate the cost of a Footprint in a given map.\n", + "\n", + "## Examples and Demos\n", + "All of these can be found in thepackage.\n", + "Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user:\n", + "Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'from\\n'\n", + " 'nav2_simple_commander.robot_navigator\\n'\n", + " 'import\\n'\n", + " 'BasicNavigator\\n'\n", + " 'import\\n'\n", + " 'rclpy\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'nav\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ')\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# if autostarted, else use lifecycleStartup()\\n'\n", + " '# ...\\n'\n", + " 'path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getPath\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ',\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'smoothed_path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'smoothPath\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_duration\\n'\n", + " '>\\n'\n", + " '600\\n'\n", + " ':\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'cancelTask\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'You may use this simple commander preempt commands of the same '\n", + " 'type (e.g. you can preempt agoToPose()with anothergoToPose()) '\n", + " 'but you must explicitly cancel a current command and issue a new '\n", + " 'one if switching betweengoToPose(),goThroughPoses(), '\n", + " 'orfollowWaypoints().',\n", + " 'filename': 'followWaypoints()',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: About and Contact\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## About\n", + "Navigation is a community effort to lower the barrier of entry of mobile robotics technology for all.\n", + "This project is one of the flagship projects along with MoveIt that acts as an applications entry point and frameworks for ROS.\n", + "Navigation in ROS 2 builds on the wild success of the original Navigation Stack (Nav Stack) in ROS (1).\n", + "This project has been used by researchers, educators, and industry for over 10 years.\n", + "There are very few projects that have lasted as long or were as successful as ROS (1) Navigation.\n", + "We would like to thank David Lu!! and Mike Ferguson for their tireless over the span of a decade to keep the Nav Stack alive and well.\n", + "Without their hard work, this project would not have been able to happen.\n", + "For a list of robots using Navigation2, seeRobots Using.\n", + "Aslas, as time moves on, so must we.\n", + "ROS (1) had a great run and those of us that build projects using it will remember it fondly(ish).\n", + "With change comes possibilities.\n", + "Navigation2 builds on the success but redesigns the framework to be more flexible and the feedback gathered over 10 years.\n", + "We strive to create an open community and encourage new ROS users and experts alike to collaborate.\n", + "However, that can’t happen without your issues, pull requests, and support.\n", + "Navigation, like all open-source projects, is kept going by a dedicated group of developers, maintainers, users, and collaborators.\n", + "We would like to thank here our current and past contributors and maintainers.\n", + "If you or your organization are interested in sponsoring Navigation or any work around it, please reach out to the current project lead.\n", + "Our current leadership team includes:\n", + "Our former leadership team includes:\n", + "\n", + "## Contact\n", + "If you are interested in contacting someone about Navigation, ROS 2, or related projects, please email the project leader or emailinfo@opennav.org.\n", + "We intentionally make our emails easy to find.\n", + "If your inquiry relates to bugs or open-source feature requests, consider posting a ticket on our GitHub project.\n", + "If your inquiry relates to configuration support or private feature development, reach out and we may be able to connect you with\n", + "independent consultants or contractors that know this project well.\n", + "Check out the Navigation 2Slackcommunity.\n", + "\n", + "=== Document ===\n", + "Title: Using Collision Monitor\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally.\n", + "Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Configuring Collision Monitor\n", + "The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice.\n", + "For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot:\n", + "If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value.\n", + "For the cases when obstacles are dangerously close to the robot, inner stop zone will work.\n", + "For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow:\n", + "For the working configuration, at least one data source should be added.\n", + "In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node:\n", + "Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup.\n", + "The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows:\n", + "\n", + "## Configuring Collision Monitor with VelocityPolygon\n", + "For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking.\n", + "In general, here are the steps to configure the Collision Monitor withVelocityPolygontype:\n", + "In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits.\n", + "Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits:\n", + "For holomic robots:\n", + "For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection.\n", + "Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity:\n", + "\n", + "## Preparing Nav2 stack\n", + "The Collision Monitor is designed to operate below Nav2 as an independent safety node.\n", + "It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions.\n", + "If no such zone is triggered, then thecmd_velmessage is used.\n", + "Else, it is scaled or set to stop as appropriate.\n", + "By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor:\n", + "If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement.\n", + "\n", + "## Demo Execution\n", + "Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run.\n", + "For that, run Nav2 stack as written inGetting Started:\n", + "In parallel console, launch Collision Monitor node by using its launch-file:\n", + "Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below:\n", + "Set the initial pose and then put Nav2 goal on map.\n", + "The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"',\n", + " 'context': 'If more than 3 points will appear inside a slowdown box, the '\n", + " 'robot will decrease its speed to30%from its value.\\n'\n", + " 'For the cases when obstacles are dangerously close to the robot, '\n", + " 'inner stop zone will work.\\n'\n", + " 'For this setup, the following lines should be added '\n", + " 'intocollision_monitor_params.yamlparameters file. Stop box is '\n", + " 'named asPolygonStopand slowdown bounding box - asPolygonSlow:',\n", + " 'filename': 'PolygonSlow',\n", + " 'language': 'unknown'},\n", + " {'code': 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'For the working configuration, at least one data source should '\n", + " 'be added.\\n'\n", + " 'In current demonstration, it is used laser scanner '\n", + " '(thoughPointCloud2and Range/Sonar/IR sensors are also possible), '\n", + " 'which is described by the following lines for Collision Monitor '\n", + " 'node:',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'collision_monitor\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'cmd_vel_in_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel_smoothed\"\\n'\n", + " 'cmd_vel_out_topic\\n'\n", + " ':\\n'\n", + " '\"cmd_vel\"\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'source_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'stop_pub_timeout\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# False for Jazzy or older by default\\n'\n", + " 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"PolygonStop\"\\n'\n", + " ',\\n'\n", + " '\"PolygonSlow\"\\n'\n", + " ']\\n'\n", + " 'PolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.4,\\n'\n", + " '0.3],\\n'\n", + " '[0.4,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_stop\"\\n'\n", + " 'PolygonSlow\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.6,\\n'\n", + " '0.4],\\n'\n", + " '[0.6,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '-0.4],\\n'\n", + " '[0.0,\\n'\n", + " '0.4]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"slowdown\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " '# max_points: 3 for Humble\\n'\n", + " 'slowdown_ratio\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_slowdown\"\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"scan\"\\n'\n", + " ']\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"scan\"\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '\"scan\"',\n", + " 'context': 'Set topic names, frame ID-s and timeouts to work correctly with '\n", + " 'a default Nav2 setup.\\n'\n", + " 'The '\n", + " 'wholenav2_collision_monitor/params/collision_monitor_params.yamlfile '\n", + " 'in this case will look as follows:',\n", + " 'filename': 'nav2_collision_monitor/params/collision_monitor_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"VelocityPolygonStop\"\\n'\n", + " ']\\n'\n", + " 'VelocityPolygonStop\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"stop\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '6\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"velocity_polygon_stop\"\\n'\n", + " 'velocity_polygons\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"rotation\"\\n'\n", + " ',\\n'\n", + " '\"translation_forward\"\\n'\n", + " ',\\n'\n", + " '\"translation_backward\"\\n'\n", + " ',\\n'\n", + " '\"stopped\"\\n'\n", + " ']\\n'\n", + " 'holonomic\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'rotation\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.3,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_forward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.35,\\n'\n", + " '0.3],\\n'\n", + " '[0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.2,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'translation_backward\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.2,\\n'\n", + " '0.3],\\n'\n", + " '[0.2,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '-0.3],\\n'\n", + " '[-0.35,\\n'\n", + " '0.3]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# This is the last polygon to be checked, it should cover the '\n", + " \"entire range of robot's velocities\\n\"\n", + " '# It is used as the stopped polygon when the robot is not moving '\n", + " 'and as a fallback if the velocity\\n'\n", + " '# is not covered by any of the other sub-polygons\\n'\n", + " 'stopped\\n'\n", + " ':\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.25,\\n'\n", + " '0.25],\\n'\n", + " '[0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '-0.25],\\n'\n", + " '[-0.25,\\n'\n", + " '0.25]]\"\\n'\n", + " 'linear_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'theta_min\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'theta_max\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'Below is the example configuration using 4 sub-polygons to cover '\n", + " 'the full range of the robot’s velocity limits:',\n", + " 'filename': 'theta_max',\n", + " 'language': 'unknown'},\n", + " {'code': 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'respawn\\n'\n", + " '=\\n'\n", + " 'use_respawn\\n'\n", + " ',\\n'\n", + " 'respawn_delay\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'--ros-args'\\n\"\n", + " ',\\n'\n", + " \"'--log-level'\\n\"\n", + " ',\\n'\n", + " 'log_level\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),\\n'\n", + " '...\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_velocity_smoother::VelocitySmoother'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'velocity_smoother'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '+\\n'\n", + " '-\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " '),\\n'\n", + " '(\\n'\n", + " \"'cmd_vel_smoothed'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ')]),\\n'\n", + " '+\\n'\n", + " '[(\\n'\n", + " \"'cmd_vel'\\n\"\n", + " ',\\n'\n", + " \"'cmd_vel_nav'\\n\"\n", + " ')]),',\n", + " 'context': 'By default, the Collision Monitor is configured for usage with '\n", + " 'the Nav2 bringup package, running in parallel with '\n", + " 'thenavigation_launch.pylaunch file. For correct operation of the '\n", + " 'Collision Monitor with the Velocity Smoother, it is required to '\n", + " 'remove the Velocity Smoother’scmd_vel_smoothedremapping in '\n", + " 'thenavigation_launch.pybringup script as presented below. This '\n", + " 'will make the output topic of the Velocity Smoother to be '\n", + " 'untouched, which will be the input to the newly added Collision '\n", + " 'Monitor:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'Once Collision Monitor node has been tuned andcmd_veltopics '\n", + " 'adjusted, Collision Monitor node is ready to run.\\n'\n", + " 'For that, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_collision_monitor\\n'\n", + " 'collision_monitor_node.launch.py\\n',\n", + " 'context': 'In parallel console, launch Collision Monitor node by using its '\n", + " 'launch-file:',\n", + " 'filename': 'cmd_vel',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: TimeExpired\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The time passed to return success (s).',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Tuning Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Inflation Potential Fields\n", + "Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map.\n", + "Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice.\n", + "This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible.\n", + "So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance.\n", + "\n", + "## Robot Footprint vs Radius\n", + "Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in.\n", + "However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise.\n", + "The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided.\n", + "If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead:\n", + "\n", + "## Rotate in Place Behavior\n", + "Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box.\n", + "This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion).\n", + "Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors.\n", + "This behavior is most optimially for:\n", + "\n", + "## Planner Plugin Selection\n", + "Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases:\n", + "If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you.\n", + "Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties.\n", + "\n", + "## Controller Plugin Selection\n", + "Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time).\n", + "In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases:\n", + "All of the above controllers can handle both circular and arbitrary shaped robots in configuration.\n", + "Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns.\n", + "DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well.\n", + "MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently.\n", + "The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly.\n", + "Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources.\n", + "\n", + "## Caching Obstacle Heuristic in Smac Planners\n", + "Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking.\n", + "This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked.\n", + "Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently.\n", + "\n", + "## Costmap2D Plugins\n", + "Costmap2D has a number of plugins that you can use (including the availability for you to create your own!).\n", + "In addition, costmap filters:\n", + "-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap\n", + "-SpeedFilter: Reduces or increases robot speeds based on position\n", + "-BinaryFilter: Enables or disables a binary topic when in particular zones\n", + "Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software.\n", + "\n", + "## Nav2 Launch Options\n", + "Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files.\n", + "Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations:\n", + "\n", + "## Other Pages We’d Love To Offer\n", + "If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful!\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: NavigateThroughPoses\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '/behavior_trees/navigate_through_poses_w_replanning_and_recovery.xml\"\\n'\n", + " '/>',\n", + " 'context': 'The lowest error code in the list of '\n", + " 'theerror_code_namesparameter.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Coverage Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'coverage_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'action_server_result_timeout\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'coordinates_in_cartesian_frame\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'robot_width\\n'\n", + " ':\\n'\n", + " '2.1\\n'\n", + " 'operation_width\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'min_turning_radius\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'linear_curv_change\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'default_allow_overlap\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'default_headland_width\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'default_path_continuity_type\\n'\n", + " ':\\n'\n", + " '\"CONTINUOUS\"\\n'\n", + " 'default_path_type\\n'\n", + " ':\\n'\n", + " '\"DUBINS\"\\n'\n", + " 'default_route_type\\n'\n", + " ':\\n'\n", + " '\"BOUSTROPHEDON\"\\n'\n", + " 'default_swath_angle_type\\n'\n", + " ':\\n'\n", + " '\"BRUTE_FORCE\"\\n'\n", + " 'default_swath_type\\n'\n", + " ':\\n'\n", + " '\"LENGTH\"\\n'\n", + " 'default_turn_point_distance\\n'\n", + " ':\\n'\n", + " '0.1',\n", + " 'context': 'Foropennav_row_coverage, whether to reorder the parsed rows in '\n", + " 'the order of their``id``s.',\n", + " 'filename': 'opennav_row_coverage',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Planner Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own planner plugin.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new Planner Plugin\n", + "We will create a simple straight-line planner.\n", + "The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner.\n", + "This package can be considered as a reference for writing planner plugin.\n", + "Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories.\n", + "Let’s learn more about the methods needed to write a planner plugin.\n", + "For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner.\n", + "In planners,configure()method must set member variables from ROS parameters and any initialization required,\n", + "Here,name_+\".interpolation_resolution\"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file).\n", + "IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method.\n", + "The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class.\n", + "Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params\n", + "with\n", + "In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used..\n", + "\n", + "## 4- Run StraightLine plugin\n", + "Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'costmap_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getCostmap\\n'\n", + " '();\\n'\n", + " 'global_frame_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " '->\\n'\n", + " 'getGlobalFrameID\\n'\n", + " '();\\n'\n", + " '// Parameter initialization\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " ',\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".interpolation_resolution\"\\n'\n", + " ',\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ');',\n", + " 'context': 'In planners,configure()method must set member variables from ROS '\n", + " 'parameters and any initialization required,',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '// Checking if the goal and start state is in the global frame\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except start position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '!=\\n'\n", + " 'global_frame_\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Planner will only except goal position from %s frame\"\\n'\n", + " ',\\n'\n", + " 'global_frame_\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'clear\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " '// calculating the number of loops for current value of '\n", + " 'interpolation_resolution_\\n'\n", + " 'int\\n'\n", + " 'total_number_of_loop\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'interpolation_resolution_\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'x_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'y_increment\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '-\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'total_number_of_loop\\n'\n", + " ';\\n'\n", + " '++\\n'\n", + " 'i\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'x_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " 'start\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '+\\n'\n", + " 'y_increment\\n'\n", + " '*\\n'\n", + " 'i\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'orientation\\n'\n", + " '.\\n'\n", + " 'w\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " ';\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'global_frame_\\n'\n", + " ';\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'global_path\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'push_back\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'global_path\\n'\n", + " ';',\n", + " 'context': 'IncreatePlan()method, we need to create a path from the given '\n", + " 'start to goal poses. TheStraightLine::createPlan()is called '\n", + " 'using start pose and goal pose to solve the global path planning '\n", + " 'problem. Upon succeeding, it converts the path to '\n", + " 'thenav_msgs::msg::Pathand returns to the planner server. Below '\n", + " 'annotation shows the implementation of this method.',\n", + " 'filename': 'nav_msgs::msg::Path',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_straightline_planner\\n'\n", + " '::\\n'\n", + " 'StraightLine\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GlobalPlanner\\n'\n", + " ')',\n", + " 'context': 'To export the planner, we need to provide two lines',\n", + " 'filename': 'nav2_core::GlobalPlanner',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'produces\\n'\n", + " 'straight\\n'\n", + " 'path.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'global_planner_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'cmake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs plugin description file tosharedirectory and '\n", + " 'sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_navfn_planner::NavfnPlanner\" # For Foxy and '\n", + " 'later. In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' tolerance: 2.0\\n'\n", + " ' use_astar: false\\n'\n", + " ' allow_unknown: true\\n',\n", + " 'context': 'For Galactic or later,plugin_namesandplugin_typeshave been '\n", + " 'replaced with a singlepluginsstring vector for plugin names. The '\n", + " 'types are now defined in theplugin_namenamespace in '\n", + " 'theplugin:field (e.g.plugin:MyPlugin::Plugin). Inline comments '\n", + " 'in the code blocks will help guide you through this.',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' plugins: [\"GridBased\"]\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' GridBased:\\n'\n", + " ' plugin: \"nav2_straightline_planner::StraightLine\"\\n'\n", + " ' interpolation_resolution: 0.1\\n',\n", + " 'context': 'with',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled navigation2. Detailed '\n", + " 'instruction how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Profiling in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots.\n", + "\n", + "## Preliminaries\n", + "This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work.\n", + "Thus, we must install them.\n", + "More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information.\n", + "Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution.\n", + "\n", + "## Profile from a Node\n", + "As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within.\n", + "Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation.\n", + "It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile.\n", + "After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via:\n", + "An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file:\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## Profile from a Launch File\n", + "Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes.\n", + "As our example before, this is how we’d launch thecontroller_servernode from inside a launch file.\n", + "Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node.\n", + "Once sufficient data has been collected, cleanly exit the process with Control+C.\n", + "\n", + "## From Nav2 Bringup\n", + "Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information.\n", + "The steps within Nav2 are as follows:\n", + "It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up.\n", + "\n", + "## Interpreting Results\n", + "Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind:\n", + "This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized.\n", + "If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\napt\\ninstall\\nvalgrind\\nkcachegrind\\n',\n", + " 'context': 'Thus, we must install them.',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'},\n", + " {'code': '# CMakeLists.txt\\nadd_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'cmake\\n-DCMAKE_BUILD_TYPE\\n=\\nRelWithDebInfo\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'valgrind\\n'\n", + " '--tool\\n'\n", + " '=\\n'\n", + " 'callgrind\\n'\n", + " '[\\n'\n", + " 'your-program\\n'\n", + " ']\\n'\n", + " '[\\n'\n", + " 'program\\n'\n", + " 'options\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'kcachegrind\\n'\n", + " 'callgrind.out.XXX\\n',\n", + " 'context': 'Generally speaking, to use valgrind we need to compile with '\n", + " 'debugging information. This can be done by passing-gas a '\n", + " 'compiling option or '\n", + " 'compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our '\n", + " 'program using valgrind to capture the run-time statistics for '\n", + " 'later analysis. These are stored incallgrind.out.XXXfiles, where '\n", + " 'the suffix is the PID of the process. kcachegrind is used to '\n", + " 'visualize and analyze the results of the program execution.',\n", + " 'filename': 'callgrind.out.XXX',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '--packages-select\\n'\n", + " '\\n'\n", + " '--cmake-args\\n'\n", + " '-DCMAKE_BUILD_TYPE\\n'\n", + " '=\\n'\n", + " 'RelWithDebInfo\\n',\n", + " 'context': 'As in our generic example, for a given node, we need to compile '\n", + " 'with debug flags to capture the information for profiling with '\n", + " 'Valgrind. This can be done easily from the commandline. Note '\n", + " 'that we use--packages-selectto only compile with this flag for '\n", + " 'the packages we want to profile nodes within.',\n", + " 'filename': '--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'add_compile_options\\n(\\n-pg\\n)',\n", + " 'context': 'It is important that this should be added to both the host '\n", + " 'server and plugin packages(s) if you would like the results of a '\n", + " 'plugin’s run-time profile.',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'After either compiling method, this node should be run in its '\n", + " 'own terminal to isolate it from the rest of your system. Thus, '\n", + " 'this should not be composed in the same process as other nodes. '\n", + " 'To run a ROS 2 node with valgrind, this can be done from the '\n", + " 'commandline via:',\n", + " 'filename': 'colconbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'valgrind --tool=callgrind'\\n\"\n", + " 'nav2_controller\\n'\n", + " 'controller_server\\n'\n", + " '--ros-args\\n'\n", + " '-r\\n'\n", + " '__node:\\n'\n", + " '=\\n'\n", + " 'controller_server\\n'\n", + " '-r\\n'\n", + " 'cmd_vel:\\n'\n", + " '=\\n'\n", + " 'cmd_vel_nav\\n'\n", + " '--params-file\\n'\n", + " '/path/to/nav2_bringup/params/nav2_params.yaml\\n',\n", + " 'context': 'An example of this might be used for profiling the controller '\n", + " 'server with a particular controller plugin loaded. '\n", + " 'Bothnav2_controllerand the plugin package of interest are '\n", + " 'compiled with debug flags. In the example below, we are running '\n", + " 'a ROS 2 node with remapped topics and a path to its parameter '\n", + " 'file:',\n", + " 'filename': 'nav2_controller',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_controller_server_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bringup\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/params/nav2_params.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_controller'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e valgrind --tool=callgrind'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'As our example before, this is how we’d launch '\n", + " 'thecontroller_servernode from inside a launch file.',\n", + " 'filename': 'controller_server',\n", + " 'language': 'unknown'},\n", + " {'code': 'kcachegrind\\ncallgrind.out.XXX\\n',\n", + " 'context': 'Once you have yourcallgrindresults, regardless of if you did it '\n", + " 'through a node, launch file, Nav2, or elsewhere, now we can '\n", + " 'analyze the results from the profiler to identify bottlenecks or '\n", + " 'potential areas of improvement. Usingkcachegrind:',\n", + " 'filename': 'kcachegrind',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DWB Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Controller\n", + "\n", + "\n", + "## Plugins\n", + "The plugins listed below are inside thedwb_pluginsnamespace.\n", + "\n", + "## Trajectory Critics\n", + "The trajectory critics listed below are inside thedwb_criticsnamespace.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# controller server parameters (see Controller Server for more '\n", + " 'info)\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# DWB controller parameters\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'debug_trajectory_details\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'min_vel_x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'min_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'max_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_theta\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_speed_xy\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_speed_xy\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'min_speed_theta\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_x\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'acc_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_theta\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'decel_lim_x\\n'\n", + " ':\\n'\n", + " '-2.5\\n'\n", + " 'decel_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'decel_lim_theta\\n'\n", + " ':\\n'\n", + " '-3.2\\n'\n", + " 'vx_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'vy_samples\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'vtheta_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'sim_time\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'linear_granularity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'angular_granularity\\n'\n", + " ':\\n'\n", + " '0.025\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'trans_stopped_velocity\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'short_circuit_trajectory_evaluation\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'limit_vel_cmd_in_traj\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"RotateToGoal\"\\n'\n", + " ',\\n'\n", + " '\"Oscillation\"\\n'\n", + " ',\\n'\n", + " '\"BaseObstacle\"\\n'\n", + " ',\\n'\n", + " '\"GoalAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathDist\"\\n'\n", + " ',\\n'\n", + " '\"GoalDist\"\\n'\n", + " ']\\n'\n", + " 'BaseObstacle.scale\\n'\n", + " ':\\n'\n", + " '0.02\\n'\n", + " 'PathAlign.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalAlign.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'PathAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'GoalAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'PathDist.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalDist.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'RotateToGoal.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'RotateToGoal.slowing_factor\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'RotateToGoal.lookahead_time\\n'\n", + " ':\\n'\n", + " '-1.0',\n", + " 'context': 'The trajectory critics listed below are inside '\n", + " 'thedwb_criticsnamespace.',\n", + " 'filename': 'dwb_critics',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: AMCL\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'amcl\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'alpha1\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha2\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha3\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha4\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha5\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'beam_skip_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'beam_skip_error_threshold\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'beam_skip_threshold\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'do_beamskip\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'global_frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'lambda_short\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'laser_likelihood_max_dist\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'laser_max_range\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'laser_min_range\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'laser_model_type\\n'\n", + " ':\\n'\n", + " '\"likelihood_field\"\\n'\n", + " 'max_beams\\n'\n", + " ':\\n'\n", + " '60\\n'\n", + " 'max_particles\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'min_particles\\n'\n", + " ':\\n'\n", + " '500\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'pf_err\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'pf_z\\n'\n", + " ':\\n'\n", + " '0.99\\n'\n", + " 'recovery_alpha_fast\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'recovery_alpha_slow\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'resample_interval\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'robot_model_type\\n'\n", + " ':\\n'\n", + " '\"nav2_amcl::DifferentialMotionModel\"\\n'\n", + " 'save_pose_rate\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'sigma_hit\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'tf_broadcast\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'update_min_a\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'update_min_d\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'z_hit\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'z_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_rand\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'z_short\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'scan_topic\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'set_initial_pose\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'always_reset_initial_pose\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'first_map_only\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'initial_pose\\n'\n", + " ':\\n'\n", + " 'x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'first_map_only_',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GoalAlignCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": GoalAlignCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Detailed Behavior Tree Walkthrough\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document serves as a reference guide to the main behavior tree (BT) used in Nav2.\n", + "There are many example behavior trees provided innav2_bt_navigator/behavior_trees,\n", + "but these sometimes have to be re-configured based on the application of the robot.\n", + "The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail.\n", + "\n", + "## Prerequisites\n", + "\n", + "\n", + "## Navigate To Pose With Replanning and Recovery\n", + "The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml.\n", + "This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions.\n", + "BTs are primarily defined in XML. The tree shown above is represented in XML as follows.\n", + "This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time.\n", + "These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree.\n", + "This can be represented in the following way:\n", + "TheNavigationsubtree mainly involves actual navigation behavior:\n", + "TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally.\n", + "The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail\n", + "(path calculation or path following), contextual recoveries will be attempted.\n", + "If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE.\n", + "The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures.\n", + "This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6).\n", + "\n", + "## Navigation Subtree\n", + "Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree.\n", + "The XML of this subtree is as follows:\n", + "This subtree has two primary actionsComputePathToPoseandFollowPath.\n", + "If either of these two actions fail, they will attempt to clear the failure contextually.\n", + "The crux of the tree can be represented with only one parent and two children nodes like this:\n", + "The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked.\n", + "While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around.\n", + "Both theComputePathToPoseand theFollowPathfollow the same general structure.\n", + "The below is theComputePathToPosesubtree:\n", + "The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree.\n", + "The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap.\n", + "Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries.\n", + "The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below:\n", + "\n", + "## Recovery Subtree\n", + "TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree.\n", + "In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient).\n", + "And the XML snippet:\n", + "The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received.\n", + "If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries.\n", + "This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”.\n", + "These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree\n", + "in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge).\n", + "If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are:\n", + "UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree.\n", + "If this renavigation was not successful, the next child of theRoundRobinwill be ticked.\n", + "For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE:\n", + "(for the sake of this example, let’s assume that the goal is never updated).\n", + "If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure).\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'BTs are primarily defined in XML. The tree shown above is '\n", + " 'represented in XML as follows.',\n", + " 'filename': 'navigate_to_pose_w_replanning_and_recovery.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'This happens until thenumber_of_retriesfor the '\n", + " 'parentRecoveryNodeis exceeded (which by default is 6).',\n", + " 'filename': 'RecoveryNode',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The XML of this subtree is as follows:',\n", + " 'filename': 'Recovery',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'And the XML snippet:',\n", + " 'filename': 'Navigation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Getting Involved\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Getting Involved\n", + "If you’re interested in getting involved in Navigation 2, first of all, welcome!\n", + "We encourage everyone to get involved from students, to junior developers, to senior developers, and executives.\n", + "There’s something to do for everyone from bug fixes, to feature development, new algorithms, and refactoring.\n", + "All ROS 2 TSC Working Groups have their meetings on theworking group calendar.\n", + "Here, you can find the date and time of the Navigation2 working group meeting. Make sure you’re checking in your local timezone.\n", + "From this calendar, you can add yourself to the event so it will appear on your google calendar and get the event link to the call through Google Hangouts.\n", + "We encourage everyone interested to come to the meeting to introduce yourself, your project, and see what everyone is working on.\n", + "Further,ROS Discourseis a good place to follow larger discussions happening in the community and announcements. This isnotthe correct place to post questions or ask for assistance. Please visitROS Answersfor Q&A.\n", + "Lastly, we have aCommunity Slackwhere we chat in real-time about topics in public channels or sidebar maintainers on individual projects via PMs. If you’re interested in contributing to Nav2, this is a great place to join!\n", + "If you’re looking to contribute code or bugs, please see the Process section below.\n", + "Over time, for developers that have an interest and have shown technical competence in an area of the stack, we elevate developers to a maintainers status.\n", + "That allows push rights to our protected branches, first-reviewers rights, and getting your name onAbout and Contact.\n", + "There currently is not a clear process for getting to be a maintainer, but if you’ve been involved and contributing over a duration of several months, you may be a good candidate and should email the project lead listed onAbout and Contact.\n", + "\n", + "## Process\n", + "After you’ve introduced yourself in a working group meeting (recommended, not required), you’re ready to get started!\n", + "We recommend a typical open-source project flow and value detail and transparency.\n", + "If you commit to something and need to pull back, say so.\n", + "We all know priorities change and appreciate the heads up so that task can go into the open queue of tasks.\n", + "The process is simple and is as follow:\n", + "Note: We take code quality seriously and strive for high-quality and consistent code.\n", + "We make use of the linting and static analysis tools provided in ROS 2 (ament_cpplint,ament_uncrustify,ament_cppcheck, etc).\n", + "All PRs are built in CI with the appropriate ROS distributions and run through a set of unit and system level tests including static analysis.\n", + "You can see the results of these tests in the pull request.\n", + "It is expected for feature development for tests to cover this work to be added.\n", + "If any documentation must be updated due to your changes, that should be included in your pull request.\n", + "\n", + "## Licensing\n", + "Licensing is very important to open source projects. It helps ensure the\n", + "software continues to be available under the terms that the author\n", + "desired.\n", + "Because much of the source code is ported from other ROS 1 projects, each\n", + "package has it’s own license. Contributions should be made under the predominant\n", + "license of that package. Entirely new packages should be made available under\n", + "theApache 2.0 license.\n", + "A license tells you what rights you have as a developer, as provided by\n", + "the copyright holder. It is important that the contributor fully\n", + "understands the licensing rights and agrees to them. Sometimes the\n", + "copyright holder isn’t the contributor, such as when the contributor is\n", + "doing work on behalf of a company.\n", + "If for some reason Apache 2.0 or BSD licenses are not appropriate for your work, please get in contact with a project maintainer and discuss your concerns or requirements.\n", + "We may consider special exceptions for exceptional work, within reason (we will not accept any licenses that makes it unsuitable for commercial use).\n", + "\n", + "## Developer Certification of Origin (DCO)\n", + "To make a good faith effort to ensure licensing criteria are met,\n", + "Nav2 encourages the Developer Certificate of Origin (DCO) process\n", + "to be followed.\n", + "The DCO is an attestation attached to every contribution made by a\n", + "developer. In the commit message of the contribution, (described more\n", + "fully later in this document), the developer simply adds aSigned-off-bystatement and thereby agrees to the DCO.\n", + "In practice, its easier to justgitcommit-s-m\"commitmessage.\".\n", + "Where-sadds this automatically.\n", + "If you forgot to add this to a commit, it is easy to append via:gitcommit--amend-s.\n", + "When a developer submits a patch, it is a commitment that the\n", + "contributor has the right to submit the patch per the license. The DCO\n", + "agreement is shown below and athttp://developercertificate.org/.\n", + "\n", + "Code Blocks:\n", + "[{'code': \"Developer's Certificate of Origin 1.1\\n\"\n", + " '\\n'\n", + " 'By making a contribution to this project, I certify that:\\n'\n", + " '\\n'\n", + " '(a) The contribution was created in whole or in part by me and I\\n'\n", + " ' have the right to submit it under the open source license\\n'\n", + " ' indicated in the file; or\\n'\n", + " '\\n'\n", + " '(b) The contribution is based upon previous work that, to the\\n'\n", + " ' best of my knowledge, is covered under an appropriate open\\n'\n", + " ' source license and I have the right under that license to\\n'\n", + " ' submit that work with modifications, whether created in whole\\n'\n", + " ' or in part by me, under the same open source license (unless\\n'\n", + " ' I am permitted to submit under a different license), as\\n'\n", + " ' Indicated in the file; or\\n'\n", + " '\\n'\n", + " '(c) The contribution was provided directly to me by some other\\n'\n", + " ' person who certified (a), (b) or (c) and I have not modified\\n'\n", + " ' it.\\n'\n", + " '\\n'\n", + " '(d) I understand and agree that this project and the contribution\\n'\n", + " ' are public and that a record of the contribution (including\\n'\n", + " ' all personal information I submit with it, including my\\n'\n", + " ' sign-off) is maintained indefinitely and may be redistributed\\n'\n", + " ' consistent with this project or the open source license(s)\\n'\n", + " ' involved.\\n',\n", + " 'context': 'When a developer submits a patch, it is a commitment that the\\n'\n", + " 'contributor has the right to submit the patch per the license. '\n", + " 'The DCO\\n'\n", + " 'agreement is shown below and athttp://developercertificate.org/.',\n", + " 'filename': 'gitcommit--amend-s',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: ProgressCheckerSelector\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'The output selected ProgressChecker id. This '\n", + " 'selected_progress_checker string is usually passed to the '\n", + " 'FollowPath behavior via the progress_checker_id input port.',\n", + " 'filename': 'transientlocal',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Spin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Output Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Spin error code. SeeSpinaction message for the enumerated set of '\n", + " 'error codes.',\n", + " 'filename': 'Spin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: SimpleGoalChecker\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_controller plugin name defined in thegoal_checker_plugin_idparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Smoother Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Smoother Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Simple Commander API\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage.\n", + "A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults).\n", + "You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints().\n", + "\n", + "## Commander API\n", + "The methods provided by the basic navigator are shown below, with inputs and expected returns.\n", + "If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype.\n", + "New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches.\n", + "\n", + "## Costmap API\n", + "This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API.\n", + "\n", + "## Footprint Collision Checker API\n", + "This is a Python3 API for a Footprint Collision Checker.\n", + "It provides the needed methods to manipulate the coordinates\n", + "and calculate the cost of a Footprint in a given map.\n", + "\n", + "## Examples and Demos\n", + "All of these can be found in thepackage.\n", + "Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user:\n", + "Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'from\\n'\n", + " 'nav2_simple_commander.robot_navigator\\n'\n", + " 'import\\n'\n", + " 'BasicNavigator\\n'\n", + " 'import\\n'\n", + " 'rclpy\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'nav\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ')\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# if autostarted, else use lifecycleStartup()\\n'\n", + " '# ...\\n'\n", + " 'path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getPath\\n'\n", + " '(\\n'\n", + " 'init_pose\\n'\n", + " ',\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'smoothed_path\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'smoothPath\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '# ...\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_duration\\n'\n", + " '>\\n'\n", + " '600\\n'\n", + " ':\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'cancelTask\\n'\n", + " '()\\n'\n", + " '# ...\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'nav\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'You may use this simple commander preempt commands of the same '\n", + " 'type (e.g. you can preempt agoToPose()with anothergoToPose()) '\n", + " 'but you must explicitly cancel a current command and issue a new '\n", + " 'one if switching betweengoToPose(),goThroughPoses(), '\n", + " 'orfollowWaypoints().',\n", + " 'filename': 'followWaypoints()',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dynamic Object Following\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely.\n", + "This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application:\n", + "The requirements for this task are as follows:\n", + "The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest,\n", + "send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Create the Behavior Tree\n", + "Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow:\n", + "First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node.\n", + "We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received.\n", + "To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance.\n", + "Now, you may save this behavior tree and use it in our navigation task.\n", + "For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage.\n", + "\n", + "## 1- Setup Rviz clicked point\n", + "We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to\n", + "publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone\n", + "this repo in your workspace, build, and type in a terminal.\n", + "ros2runnav2_test_utilsclicked_point_to_pose\n", + "Optionally, you can remap this topic in your rviz configuration file togoal_updates.\n", + "\n", + "## 2- Run Dynamic Object Following in Nav2 Simulation\n", + "Start Nav2 in one terminal:\n", + "ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml\n", + "Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial.\n", + "When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest!\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Let’s start from this simple behavior tree. This behavior tree '\n", + " 'replans a new path at 1 hz and passes that path to the '\n", + " 'controller to follow:',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'First, let’s make this behavior run until there’s a failure. For '\n", + " 'this purpose, we will use theKeepRunningUntilFailurecontrol '\n", + " 'node.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'We will then use the decoratorGoalUpdaterto accept updates of '\n", + " 'the dynamic object pose we’re trying to follow. This node takes '\n", + " 'as input the current goal and subscribes to the '\n", + " 'topic/goal_update. It sets the new goal asupdated_goalif a new '\n", + " 'goal on that topic is received.',\n", + " 'filename': 'updated_goal',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To stay at a certain distance from the target, we will use the '\n", + " 'action nodeTruncatePath. This node modifies a path making it '\n", + " 'shorter so we don’t try to navigate into the object of interest. '\n", + " 'We can set up the desired distance to the goal using the input '\n", + " 'portdistance.',\n", + " 'filename': 'distance',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: IsBatteryLow\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Checks if battery is low by subscribing to '\n", + " 'asensor_msgs/BatteryStatetopic and checking if battery '\n", + " 'percentage/voltage is below a specified minimum value.\\n'\n", + " 'By default percentage (in range 0 to 1) is used to check for low '\n", + " 'battery. Set theis_voltageparameter totrueto use voltage.\\n'\n", + " 'Returns SUCCESS when battery percentage/voltage is lower than '\n", + " 'the specified value, FAILURE otherwise.',\n", + " 'filename': 'is_voltage',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Velocity Smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Velocity Smoother Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'velocity_smoother\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'smoothing_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'scale_velocities\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'feedback\\n'\n", + " ':\\n'\n", + " '\"OPEN_LOOP\"\\n'\n", + " 'max_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '2.5\\n'\n", + " ']\\n'\n", + " 'min_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '-0.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '-2.5\\n'\n", + " ']\\n'\n", + " 'deadband_velocity\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'velocity_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'max_accel\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '2.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '3.2\\n'\n", + " ']\\n'\n", + " 'max_decel\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '-2.5\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '-3.2\\n'\n", + " ']\\n'\n", + " 'odom_topic\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'odom_duration\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'use_realtime_priority\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'false',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: XYTheta Iterator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: OscillationCritic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + ": OscillationCritic critic name defined in the.criticsparameter defined inDWB Controller.\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: InputAtWaypoint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_waypoint_follower plugin name defined in thewaypoint_task_executor_plugin_idparameter inWaypoint Follower.\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: IsPathValid\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Checks to see if the global path is valid. If there is a\\n'\n", + " 'obstacle along the path, the condition returns FAILURE, '\n", + " 'otherwise\\n'\n", + " 'it returns SUCCESS.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Docker for Development: Zero to Hero\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker.\n", + "This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing.\n", + "If you know some basics about Docker already, you can skip to later sections about development and deployment.\n", + "You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it.\n", + "The same process template can be used for other company applications and projects as well.\n", + "Some other useful resources:\n", + "\n", + "## Preliminaries\n", + "Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer.\n", + "This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources.\n", + "By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances.\n", + "It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs.\n", + "For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots.\n", + "In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers.\n", + "Thus,containersare self-contained, runnable instances of the dockerimage.\n", + "TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment.\n", + "The Dockerfile instruct sets have a number of options such as:\n", + "Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set.\n", + "Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles.\n", + "In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript.\n", + "This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go.\n", + "But these can be used to do more advanced things like run your application or trigger other events.\n", + "\n", + "## Important Docker Commands\n", + "Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward.\n", + "There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day.\n", + "Over the tutorial, build up some important option flags for each, but for now lets talk about the basics:\n", + "\n", + "## Exploring Your First Container\n", + "Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling.\n", + "Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves.\n", + "You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete.\n", + "If you then attempt to run this image as a container (the instance of the image):\n", + "You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it?\n", + "OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed.\n", + "If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container.\n", + "This is easy to do with the-itflags:\n", + "You should now see a terminal session open with a command prompt ofroot@:/#.\n", + "This is your docker container.\n", + "Take a look around, it should look like any other linux OS.\n", + "If you go into/opt/ros/rolling, it should look familiar to you!\n", + "If you open a new terminal and runsudodockerps, you should see now one container instance running on your system.\n", + "The ID of this container should match the hash in your command prompt.\n", + "We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around:\n", + "Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer.\n", + "In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running.\n", + "If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers.\n", + "You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a.\n", + "While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing!\n", + "That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen.\n", + "When we run the image again, we’re generating a brand new, clean instance of the image.\n", + "Nothing persists. This is an important behavior to understand moving forward.\n", + "For development, this is nightmare fuel of losing a day’s work by hitting the wrong button.\n", + "For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate.\n", + "We’ll discuss how to persist data between sessions later on in the tutorial, so fear not!\n", + "With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other.\n", + "Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container.\n", + "This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal).\n", + "Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command.\n", + "Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go.\n", + "In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container!\n", + "Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands.\n", + "If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics.\n", + "What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer.\n", + "Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know.\n", + "This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer).\n", + "In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer!\n", + "Lets talk about how to keep a container running for longer than than your interactive terminal session.\n", + "There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached.\n", + "Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag.\n", + "You’ll see the command run for a moment and return.sudodockerpsshould now show a container running.\n", + "Copy that container ID and we can nowattachto it:\n", + "You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container.\n", + "If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running.\n", + "In either case, you can show that to yourself usingps.\n", + "If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit.\n", + "Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with.\n", + "\n", + "## Understanding ROS Docker Images\n", + "Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail.\n", + "OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use.\n", + "For each distribution, there are a couple of variants:\n", + "These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form.\n", + "Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user.\n", + "Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment.\n", + "We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included.\n", + "You can pull and use them the same way as before, for example:\n", + "Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries.\n", + "In general, the desktop installs are withosrf/`and the ros core and base are without.\n", + "\n", + "## For Docker-Based Development\n", + "As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited.\n", + "If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it.\n", + "That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside.\n", + "That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container.\n", + "An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time.\n", + "We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward.\n", + "It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container.\n", + "If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker:\n", + "If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace.\n", + "Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing!\n", + "This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons).\n", + "However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container.\n", + "Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application.\n", + "That way, you can simply jump into the container and immediately start building.\n", + "\n", + "## Building a Development Image\n", + "Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles.\n", + "Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image.\n", + "Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container.\n", + "In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies.\n", + "Once these steps conclude, the image is all setup for any later Nav2 build.\n", + "You can build this image usingdockerbuild\n", + "Where-tsets the tagged name of the container for later use.\n", + "Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container.\n", + "This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages.\n", + "For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development,\n", + "it is useful to upgrade so that your source code can build against the latest and greatest.\n", + "\n", + "## Visualizations from Docker\n", + "Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears.\n", + "Docker’s isolation isn’t just for networking, but also in visualization and other assets.\n", + "Thus, we must specifically enable carve outs for GUIs to appear on our screens.\n", + "Putting it altogether, you should now be able to open rviz2 inside of the docker container!\n", + "At this point, if you have an error remaining, please check docs for the right flags to use.\n", + "(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.)\n", + "If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version.\n", + "\n", + "## For Docker-Based Deployment\n", + "We won’t belabor the details, but Docker is not just for development, but for application deployment as well.\n", + "You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems.\n", + "Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application.\n", + "For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar.\n", + "You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup.\n", + "\n", + "## Conclusion\n", + "At the end of this, you should be able to now:\n", + "Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work.\n", + "Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs.\n", + "If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware.\n", + "As for potential steps forward:\n", + "We hope that’s enough to get you started!\n", + "– Your Friendly Neighborhood Navigators\n", + "\n", + "## Appendix\n", + "\n", + "\n", + "## Nav2 Development Image\n", + "This container downloads, but does not install Nav2.\n", + "Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling.\n", + "\n", + "## Nav2 Deployment Image\n", + "This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2.\n", + "From here, you can go to theGetting Startedto test it out!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\ndocker\\npull\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets start this tutorial with getting the latest-and-greatest of '\n", + " 'ROS 2 Rolling.\\n'\n", + " 'Using the OSRF DockerHub server, we can pull down a number of '\n", + " 'different ROS 2 docker images to work with without having to '\n", + " 'create a Dockerfile or build them ourselves.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " 'rolling-desktop-full:\\n'\n", + " 'Pulling\\n'\n", + " 'from\\n'\n", + " 'osrf/ros\\n'\n", + " '31bd5f451a84:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " 'd36cae3fb404:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '8d68f36a56a7:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '299f725c4bf1:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '6e16227afc48:\\n'\n", + " 'Already\\n'\n", + " 'exists\\n'\n", + " '02457a85146c:\\n'\n", + " 'Downloading\\n'\n", + " '83\\n'\n", + " '.7MB/106.5MB\\n'\n", + " 'fe0cbdee2808:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '4b4dbddf506a:\\n'\n", + " 'Downloading\\n'\n", + " '92\\n'\n", + " '.86MB/98.14MB\\n'\n", + " '0da90b52c355:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '64de492566b2:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " '167d95ac0fce:\\n'\n", + " 'Download\\n'\n", + " 'complete\\n'\n", + " '\\n'\n", + " 'e727072615d0:\\n'\n", + " 'Downloading\\n'\n", + " '82\\n'\n", + " '.61MB/809.8MB\\n'\n", + " 'd15e176ed0af:\\n'\n", + " 'Waiting\\n',\n", + " 'context': 'You should then see the following, where the image is being '\n", + " 'pulled down in multiple layers and finally returning the '\n", + " 'terminal once complete.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'If you then attempt to run this image as a container (the '\n", + " 'instance of the image):',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You should see that it runs for a second then exits the '\n", + " 'terminal. Yay! It works! But… that’s not very useful, now is '\n", + " 'it?\\n'\n", + " 'OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 '\n", + " 'installation and so the program returns as completed.\\n'\n", + " 'If we want to get into the container to do something useful for '\n", + " 'ourselves in that environment, we need to open an interactive '\n", + " 'terminal session with the container.\\n'\n", + " 'This is easy to do with the-itflags:',\n", + " 'filename': '-it',\n", + " 'language': 'unknown'},\n", + " {'code': 'echo\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '# --> rolling\\n'\n", + " '\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " \"# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello \"\n", + " \"World: 1'\\n\"\n", + " '\\n'\n", + " 'touch\\n'\n", + " 'navigator_dockerlayer.txt\\n'\n", + " 'l\\n'\n", + " '# <-- you should see this file',\n", + " 'context': 'If you open a new terminal and runsudodockerps, you should see '\n", + " 'now one container instance running on your system.\\n'\n", + " 'The ID of this container should match the hash in your command '\n", + " 'prompt.\\n'\n", + " 'We mentioned before that the container on spin up will '\n", + " 'automatically source the ROS installation, so we should be able '\n", + " 'to immediately play around:',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'ps\\n'\n", + " '-a\\n'\n", + " 'CONTAINER\\n'\n", + " 'ID\\n'\n", + " 'IMAGE\\n'\n", + " 'COMMAND\\n'\n", + " 'CREATED\\n'\n", + " 'STATUS\\n'\n", + " 'PORTS\\n'\n", + " 'NAMES\\n'\n", + " '7ec0e0b7487f\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '5\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " 'About\\n'\n", + " 'a\\n'\n", + " 'minute\\n'\n", + " 'ago\\n'\n", + " 'strange_tesla\\n'\n", + " '9ccd97ac14f9\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\"/ros_entrypoint.sh …\"\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'Exited\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '7\\n'\n", + " 'minutes\\n'\n", + " 'ago\\n'\n", + " 'zen_perlman\\n',\n", + " 'context': 'Nice! It all works. Now, if we exit our interactive session '\n", + " '(typeexit), we should reenter our computer.\\n'\n", + " 'In that second terminal, if you rerunsudodockerps, you should '\n", + " 'see that the list of containers is now empty since our container '\n", + " 'is no longer running.\\n'\n", + " 'If you want to see a full list of containers, including exited '\n", + " 'containers, you can use the flag-ato display all containers.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nrun\\n-it\\nosrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'You can see that our container exited successfully. If we now '\n", + " 'run our docker image again, you should see it back listed '\n", + " 'without-a.',\n", + " 'filename': '-a',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nexec\\n-it\\nbce2ad161bf7\\nbash\\n# <-- use your ID',\n", + " 'context': 'With our new container still open, lets explore how to work with '\n", + " 'one container across multiple terminals. If you were to run '\n", + " 'thedockerruncommand in two terminals, you’d make two separate '\n", + " 'containers isolated from each other.\\n'\n", + " 'Instead, we need to open a new session in the container. Looking '\n", + " 'at the terminal’s hash orsudodockerpsto find its ID, use '\n", + " 'theexeccommand to execute the commandbashin the container.',\n", + " 'filename': 'bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'touch\\n'\n", + " 'navigator_alligator.txt\\n'\n", + " 'ls\\n'\n", + " '# <-- see the new file\\n'\n", + " '# move to the other terminal\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '# <-- also see new file',\n", + " 'context': 'In either terminal session in the container, if you create a new '\n", + " 'file, you should be able to see it in the other since this is '\n", + " 'the same container!',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_cpp\\n'\n", + " 'talker\\n'\n", + " 'ros2\\n'\n", + " 'run\\n'\n", + " 'demo_nodes_py\\n'\n", + " 'listener\\n',\n", + " 'context': 'Now we can do something fun while we have both terminals of the '\n", + " 'same docker container open. Lets run the classic talker/listener '\n", + " 'demo. In each of the two terminals, run one of these commands.',\n", + " 'filename': '/opt/ros/rolling/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\nros2\\ntopic\\nlist\\n/parameter_events\\n/rosout\\n',\n", + " 'context': 'If you now open a third terminal to your computer and '\n", + " 'runros2topiclist, you’ll see a notable lack of topics.',\n", + " 'filename': 'ros2topiclist',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'What gives? The container is isolated from your host system, so '\n", + " 'anything happening in the container is currently unavailable to '\n", + " 'your main computer.\\n'\n", + " 'Lets exit our two container terminal instances (exit) and talk '\n", + " 'about some moredockerrunflags that are useful to know.\\n'\n", + " 'This time, we want to expose ROS to our broader system, '\n", + " 'including our host computer. This time, we’ll use the '\n", + " 'flag--net=host, this sets the network to look like the host '\n", + " 'system (i.e. your computer).',\n", + " 'filename': '--net=host',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'ros2\\n'\n", + " 'topic\\n'\n", + " 'echo\\n'\n", + " '/chatter\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 0'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 1'\\n\"\n", + " '\\n'\n", + " '---\\n'\n", + " 'data:\\n'\n", + " \"'Hello World: 2'\\n\"\n", + " '\\n'\n", + " '---\\n',\n", + " 'context': 'In this session, if we run the talkerros2rundemo_nodes_pytalker, '\n", + " 'now we should be able to subscribe to it from our host computer!',\n", + " 'filename': 'ros2rundemo_nodes_pytalker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-d\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Lets talk about how to keep a container running for longer than '\n", + " 'than your interactive terminal session.\\n'\n", + " 'There are many reasons you want a container to outlive you or '\n", + " 'run in the background, so that’s what the-dflag is for, or '\n", + " 'detached.\\n'\n", + " 'Lets start off by showing that there are no containers running '\n", + " 'withsudodockerps. Next start a new container with the flag.',\n", + " 'filename': 'sudodockerps',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nattach\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You’ll see the command run for a moment and '\n", + " 'return.sudodockerpsshould now show a container running.\\n'\n", + " 'Copy that container ID and we can nowattachto it:',\n", + " 'filename': 'attach',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nstop\\ne1d7e035a824\\n# <-- use your ID',\n", + " 'context': 'You should now be in the terminal session. After you do your '\n", + " 'work, if you want to stop the container, you can exit as we have '\n", + " 'been in this tutorial (exit) and that will also stop the '\n", + " 'container.\\n'\n", + " 'If you wish to leave the container running, you can use the key '\n", + " 'sequence Control+P+Q to exit but leave the container running.\\n'\n", + " 'In either case, you can show that to yourself usingps.\\n'\n", + " 'If you left it running and now wish to stop it externally, you '\n", + " 'can do so with the following. It may take a few moments to exit.',\n", + " 'filename': 'ps',\n", + " 'language': 'unknown'},\n", + " {'code': 'steve@reese:~$\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'images\\n'\n", + " 'REPOSITORY\\n'\n", + " 'TAG\\n'\n", + " 'IMAGE\\n'\n", + " 'ID\\n'\n", + " 'CREATED\\n'\n", + " 'SIZE\\n'\n", + " 'osrf/ros\\n'\n", + " 'rolling-desktop-full\\n'\n", + " '7cd0c5068235\\n'\n", + " '6\\n'\n", + " 'days\\n'\n", + " 'ago\\n'\n", + " '3\\n'\n", + " '.86GB\\n',\n", + " 'context': 'Finally,dockerimagesis a command used to tell you what docker '\n", + " 'images you have built or pulled which are available for use. '\n", + " 'This list will expand over time and is a useful resource to see '\n", + " 'what you have to work with.',\n", + " 'filename': 'dockerimages',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'ros:rolling-ros-base\\n'\n", + " 'sudo\\n'\n", + " 'docker\\n'\n", + " 'pull\\n'\n", + " 'osrf/ros:humble-desktop\\n',\n", + " 'context': 'You can pull and use them the same way as before, for example:',\n", + " 'filename': 'osrf/ros:-ros-base',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '-v\\n'\n", + " '.:/my_ws_docker\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n'\n", + " '\\n'\n", + " 'ls\\n'\n", + " '\\n'\n", + " 'cd\\n'\n", + " 'my_ws_docker\\n'\n", + " 'touch\\n'\n", + " 'navigator_activator.txt\\n',\n", + " 'context': 'We accomplish this using the-vflag (for volume). There are other '\n", + " 'options to do this as well, but this is the most straight '\n", + " 'forward.\\n'\n", + " 'It takes in the argument in the '\n", + " 'form-vwhat/local/dir:/absolute/path/in/container.\\n'\n", + " 'If we start a container in our workspace’s root, the following '\n", + " 'will launch the docker container, sharing the host’s network, '\n", + " 'and putting your workspace (.) into the container under the '\n", + " 'directory/my_ws_docker:',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'apt\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '--from-paths\\n'\n", + " '.\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n',\n", + " 'context': 'If you go to your workspace in another terminal, you should now '\n", + " 'see that file reflected on your computer! If we run rosdep to '\n", + " 'install our dependencies in the docker container, we should now '\n", + " 'be able to build your workspace.',\n", + " 'filename': '/my_ws_docker',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\ndocker\\nbuild\\n-t\\nnav2deps:rolling\\n.\\n',\n", + " 'context': 'You can build this image usingdockerbuild',\n", + " 'filename': 'dockerbuild',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'docker\\n'\n", + " 'run\\n'\n", + " '-it\\n'\n", + " '--net\\n'\n", + " '=\\n'\n", + " 'host\\n'\n", + " '--privileged\\n'\n", + " '\\\\\\n'\n", + " '--env\\n'\n", + " '=\\n'\n", + " '\"DISPLAY=\\n'\n", + " '$DISPLAY\\n'\n", + " '\"\\n'\n", + " '\\\\\\n'\n", + " '--volume\\n'\n", + " '=\\n'\n", + " '\"\\n'\n", + " '${\\n'\n", + " 'XAUTHORITY\\n'\n", + " '}\\n'\n", + " ':/root/.Xauthority\"\\n'\n", + " '\\\\\\n'\n", + " 'osrf/ros:rolling-desktop-full\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'rviz2\\n',\n", + " 'context': 'Putting it altogether, you should now be able to open rviz2 '\n", + " 'inside of the docker container!',\n", + " 'filename': '--volume=\"${XAUTHORITY}:/root/.Xauthority\"',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n',\n", + " 'context': 'This container downloads, but does not install Nav2.\\n'\n", + " 'Instead, it pulls the dependencies so that when you run this '\n", + " 'container, you obtain everything needed to immediately start '\n", + " 'building and working with Nav2 on any ROS 2 distribution, '\n", + " 'including Rolling.',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ARG\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'FROM\\n'\n", + " 'ros:\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '-ros-core\\n'\n", + " '\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'DEBIAN_FRONTEND\\n'\n", + " '=\\n'\n", + " 'noninteractive\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--no-install-recommends\\n'\n", + " '--no-install-suggests\\n'\n", + " '\\\\\\n'\n", + " 'ros-dev-tools\\n'\n", + " '\\\\\\n'\n", + " 'wget\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For Rolling or want to build from source a particular branch / '\n", + " 'fork\\n'\n", + " '\\n'\n", + " 'WORKDIR\\n'\n", + " '/root/nav2_ws\\n'\n", + " 'RUN\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " 'RUN\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'RUN\\n'\n", + " 'rosdep\\n'\n", + " 'init\\n'\n", + " 'RUN\\n'\n", + " 'apt\\n'\n", + " 'update\\n'\n", + " '&&\\n'\n", + " 'apt\\n'\n", + " 'upgrade\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'update\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '--ignore-src\\n'\n", + " '--from-paths\\n'\n", + " 'src\\n'\n", + " '-r\\n'\n", + " 'RUN\\n'\n", + " '.\\n'\n", + " '/opt/ros/\\n'\n", + " '${\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '}\\n'\n", + " '/setup.sh\\n'\n", + " '\\\\\\n'\n", + " '&&\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# For all else, uncomment the above Rolling lines and replace with '\n", + " 'below\\n'\n", + " '# RUN rosdep init\\n'\n", + " '# RUN apt update && apt upgrade -y \\\\\\n'\n", + " '# && rosdep update \\\\\\n'\n", + " '# && apt install \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-nav2-bringup \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-navigation2 \\\\\\n'\n", + " '# ros-${NAV2_BRANCH}-turtlebot3-gazebo',\n", + " 'context': 'This image either downloads and installs Nav2 (Rolling; from '\n", + " 'source) or installs it (from binaries) to have a self contained '\n", + " 'image of everything you need to run Nav2.\\n'\n", + " 'From here, you can go to theGetting Startedto test it out!',\n", + " 'filename': 'sudo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up The URDF\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## URDF and the Robot State Publisher\n", + "As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms.\n", + "The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees.\n", + "The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment.\n", + "Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF.\n", + "\n", + "## Setting Up the Environment\n", + "In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section.\n", + "Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial.\n", + "Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot.\n", + "\n", + "## Writing the URDF\n", + "Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build.\n", + "Next, let us define some constants using XAcro properties that will be reused throughout the URDF.\n", + "Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis.\n", + "Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them.\n", + "We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color.\n", + "For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties.\n", + "Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane.\n", + "After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis.\n", + "Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location.\n", + "At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot.\n", + "Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location.\n", + "And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz.\n", + "\n", + "## Build and Launch\n", + "Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag)\n", + "Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile.\n", + "To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz\n", + "Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:\n", + "We are now ready to build our project using colcon. Navigate to the project root and execute the following commands.\n", + "After a successful build, execute the following commands to install the ROS 2 package and launch our project.\n", + "ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section.\n", + "\n", + "## Visualization using RVIZ\n", + "RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot.\n", + "As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations.\n", + "You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI.\n", + "At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section.\n", + "\n", + "## Adding Physical Properties\n", + "As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment.\n", + "Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF:\n", + "Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF.\n", + "Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF.\n", + "Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF.\n", + "Build your project and then launch RViz using the same commands in the previous section.\n", + "You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks.\n", + "For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section.\n", + "\n", + "## Conclusion\n", + "And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation.\n", + "Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--joint-state-publisher-gui\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--xacro\\n',\n", + " 'context': 'Let’s begin by installing some additional ROS 2 packages that we '\n", + " 'will be using during this tutorial.',\n", + " 'filename': 'laser_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\npkg\\ncreate\\n--build-type\\nament_cmake\\nsam_bot_description\\n',\n", + " 'context': 'Next, create a directory for your project, initialize a ROS 2 '\n", + " 'workspace and give your robot a name. For ours, we’ll be calling '\n", + " 'itsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '1\\n'\n", + " '\\n'\n", + " '2\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '4\\n'\n", + " '5\\n'\n", + " '6\\n'\n", + " '',\n", + " 'context': 'To get started, create a file '\n", + " 'namedsam_bot_description.urdfundersrc/descriptionand input the '\n", + " 'following as the initial contents of the file.',\n", + " 'filename': 'src/description',\n", + " 'language': 'unknown'},\n", + " {'code': ' 4\\n'\n", + " '\\n'\n", + " ' 5\\n'\n", + " '\\n'\n", + " ' 6\\n'\n", + " '\\n'\n", + " ' 7\\n'\n", + " '\\n'\n", + " ' 8\\n'\n", + " ' 9\\n'\n", + " '\\n'\n", + " '10\\n'\n", + " '\\n'\n", + " '11\\n'\n", + " '\\n'\n", + " '12\\n'\n", + " '\\n'\n", + " '13\\n'\n", + " '\\n'\n", + " '14\\n'\n", + " '15\\n'\n", + " '',\n", + " 'context': 'Next, let us define some constants using XAcro properties that '\n", + " 'will be reused throughout the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '',\n", + " 'context': 'For the code block block below, we access thebaseproperties from '\n", + " 'the robot constants sections we defined before using '\n", + " 'the${property}syntax. In addition, we also set the material '\n", + " 'color of the main chassis toCyan. Note that we set these '\n", + " 'parameters under thetag so they will only be applied as '\n", + " 'visual parameters which dont affect any collision or physical '\n", + " 'properties.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '',\n", + " 'context': 'After defining our base_link, we then add a joint to connect it '\n", + " 'tobase_link. In URDF, ajointelement describes the kinematic and '\n", + " 'dynamic properties between coordinate frames. For this case, we '\n", + " 'will be defining afixedjoint with the appropriate offsets to '\n", + " 'place ourbase_footprintlink in the proper location based on the '\n", + " 'description above. Remember that we want to set our '\n", + " 'base_footprint to be at the ground plane when projected from the '\n", + " 'center of the main chassis, hence we get the sum of '\n", + " 'thewheel_radiusand thewheel_zoffto get the appropriate location '\n", + " 'along the z-axis.',\n", + " 'filename': 'wheel_zoff',\n", + " 'language': 'unknown'},\n", + " {'code': '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '\\n'\n", + " '40\\n'\n", + " '\\n'\n", + " '41\\n'\n", + " '\\n'\n", + " '42\\n'\n", + " '\\n'\n", + " '43\\n'\n", + " '\\n'\n", + " '44\\n'\n", + " '\\n'\n", + " '45\\n'\n", + " '\\n'\n", + " '46\\n'\n", + " '\\n'\n", + " '47\\n'\n", + " '\\n'\n", + " '48\\n'\n", + " '\\n'\n", + " '49\\n'\n", + " '\\n'\n", + " '50\\n'\n", + " '\\n'\n", + " '51\\n'\n", + " '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '\\n'\n", + " '58\\n'\n", + " '\\n'\n", + " '59\\n'\n", + " '60\\n'\n", + " '\\n'\n", + " '61\\n'\n", + " '',\n", + " 'context': 'At the end of this code block, we will be instantiating two '\n", + " 'wheels using the macro we just made through thexacro:wheeltags. '\n", + " 'Note that we also define the parameters to have one wheel on '\n", + " 'both sides at the back of our robot.',\n", + " 'filename': 'xacro:wheel',\n", + " 'language': 'unknown'},\n", + " {'code': '63\\n'\n", + " '\\n'\n", + " '64\\n'\n", + " '\\n'\n", + " '65\\n'\n", + " '\\n'\n", + " '66\\n'\n", + " '\\n'\n", + " '67\\n'\n", + " '\\n'\n", + " '68\\n'\n", + " '\\n'\n", + " '69\\n'\n", + " '\\n'\n", + " '70\\n'\n", + " '\\n'\n", + " '71\\n'\n", + " '\\n'\n", + " '72\\n'\n", + " '\\n'\n", + " '73\\n'\n", + " '\\n'\n", + " '74\\n'\n", + " '75\\n'\n", + " '\\n'\n", + " '76\\n'\n", + " '\\n'\n", + " '77\\n'\n", + " '\\n'\n", + " '78\\n'\n", + " '\\n'\n", + " '79\\n'\n", + " '',\n", + " 'context': 'Next, we will be adding a caster wheel at the front of our '\n", + " 'robot. We will be modelling this wheel as a sphere to keep '\n", + " 'things simple. Again, we define the wheel’s geometry, material '\n", + " 'and the joint to connect it tobase_linkat the appropriate '\n", + " 'location.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " 'joint_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'joint_state_publisher_gui\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'robot_state_publisher\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'xacro\\n'\n", + " '',\n", + " 'context': 'Let’s start this section by adding some dependencies that will '\n", + " 'be required once we build this project. Open up the root of your '\n", + " 'project directory and add the following lines to '\n", + " 'yourpackage.xml(preferably after thetag)',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'launch\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'Command\\n'\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'import\\n'\n", + " 'launch_ros\\n'\n", + " 'import\\n'\n", + " 'os\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " 'pkg_share\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'substitutions\\n'\n", + " '.\\n'\n", + " 'FindPackageShare\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " '.\\n'\n", + " 'find\\n'\n", + " '(\\n'\n", + " \"'sam_bot_description'\\n\"\n", + " ')\\n'\n", + " 'default_model_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'src/description/sam_bot_description.urdf'\\n\"\n", + " ')\\n'\n", + " 'default_rviz_config_path\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'pkg_share\\n'\n", + " ',\\n'\n", + " \"'rviz/urdf_config.rviz'\\n\"\n", + " ')\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'robot_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'model'\\n\"\n", + " ')])}]\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xacro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}],\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'conditions\\n'\n", + " '.\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')\\n'\n", + " 'rviz_node\\n'\n", + " '=\\n'\n", + " 'launch_ros\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rviz2'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'arguments\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'-d'\\n\"\n", + " ',\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ')],\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'LaunchDescription\\n'\n", + " '([\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'model'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_model_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to robot urdf file'\\n\"\n", + " '),\\n'\n", + " 'launch\\n'\n", + " '.\\n'\n", + " 'actions\\n'\n", + " '.\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'rvizconfig'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'default_rviz_config_path\\n'\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Absolute path to rviz config file'\\n\"\n", + " '),\\n'\n", + " 'joint_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'joint_state_publisher_gui_node\\n'\n", + " ',\\n'\n", + " 'robot_state_publisher_node\\n'\n", + " ',\\n'\n", + " 'rviz_node\\n'\n", + " '])',\n", + " 'context': 'Next, let us create our launch file. Launch files are used by '\n", + " 'ROS 2 to bring up the necessary nodes for our package. From the '\n", + " 'root of the project, create a directory namedlaunchand '\n", + " 'adisplay.launch.pyfile within it. The launch file below launches '\n", + " 'a robot publisher node in ROS 2 that uses our URDF to publish '\n", + " 'the transforms for our robot. In addition, the launch file also '\n", + " 'automatically launches RVIZ so we can visualize our robot as '\n", + " 'defined by the URDF. Copy and paste the snippet below into '\n", + " 'yourdisplay.launch.pyfile.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'Panels:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_common/Displays\\n'\n", + " '\\n'\n", + " 'Help\\n'\n", + " 'Height:\\n'\n", + " '78\\n'\n", + " 'Name:\\n'\n", + " 'Displays\\n'\n", + " '\\n'\n", + " 'Property\\n'\n", + " 'Tree\\n'\n", + " 'Widget:\\n'\n", + " '\\n'\n", + " 'Expanded:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Global\\n'\n", + " 'Options1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/Status1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/RobotModel1/Links1\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " '/TF1\\n'\n", + " '\\n'\n", + " 'Splitter\\n'\n", + " 'Ratio:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Tree\\n'\n", + " 'Height:\\n'\n", + " '557\\n'\n", + " '\\n'\n", + " 'Visualization\\n'\n", + " 'Manager:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " '\"\"\\n'\n", + " 'Displays:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.5\\n'\n", + " '\\n'\n", + " 'Cell\\n'\n", + " 'Size:\\n'\n", + " '1\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Grid\\n'\n", + " '\\n'\n", + " 'Color:\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '160\\n'\n", + " ';\\n'\n", + " '164\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'Grid\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Alpha:\\n'\n", + " '0\\n'\n", + " '.6\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/RobotModel\\n'\n", + " '\\n'\n", + " 'Description\\n'\n", + " 'Topic:\\n'\n", + " '\\n'\n", + " 'Depth:\\n'\n", + " '5\\n'\n", + " 'Durability\\n'\n", + " 'Policy:\\n'\n", + " 'Volatile\\n'\n", + " '\\n'\n", + " 'History\\n'\n", + " 'Policy:\\n'\n", + " 'Keep\\n'\n", + " 'Last\\n'\n", + " '\\n'\n", + " 'Reliability\\n'\n", + " 'Policy:\\n'\n", + " 'Reliable\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " '/robot_description\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'RobotModel\\n'\n", + " '\\n'\n", + " 'Visual\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Name:\\n'\n", + " 'TF\\n'\n", + " '\\n'\n", + " 'Marker\\n'\n", + " 'Scale:\\n'\n", + " '0\\n'\n", + " '.3\\n'\n", + " '\\n'\n", + " 'Show\\n'\n", + " 'Arrows:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Axes:\\n'\n", + " 'true\\n'\n", + " 'Show\\n'\n", + " 'Names:\\n'\n", + " 'true\\n'\n", + " 'Enabled:\\n'\n", + " 'true\\n'\n", + " 'Global\\n'\n", + " 'Options:\\n'\n", + " '\\n'\n", + " 'Background\\n'\n", + " 'Color:\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " ';\\n'\n", + " '48\\n'\n", + " 'Fixed\\n'\n", + " 'Frame:\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " 'Frame\\n'\n", + " 'Rate:\\n'\n", + " '30\\n'\n", + " 'Name:\\n'\n", + " 'root\\n'\n", + " '\\n'\n", + " 'Tools:\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Interact\\n'\n", + " '\\n'\n", + " 'Hide\\n'\n", + " 'Inactive\\n'\n", + " 'Objects:\\n'\n", + " 'true\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/MoveCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Select\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/FocusCamera\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Measure\\n'\n", + " '\\n'\n", + " 'Line\\n'\n", + " 'color:\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '128\\n'\n", + " ';\\n'\n", + " '0\\n'\n", + " 'Transformation:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/TF\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'true\\n'\n", + " 'Views:\\n'\n", + " '\\n'\n", + " 'Current:\\n'\n", + " '\\n'\n", + " 'Class:\\n'\n", + " 'rviz_default_plugins/Orbit\\n'\n", + " '\\n'\n", + " 'Name:\\n'\n", + " 'Current\\n'\n", + " 'View\\n'\n", + " '\\n'\n", + " 'Target\\n'\n", + " 'Frame:\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Value:\\n'\n", + " 'Orbit\\n'\n", + " '(\\n'\n", + " 'rviz\\n'\n", + " ')\\n'\n", + " 'Saved:\\n'\n", + " '~\\n',\n", + " 'context': 'To keep things simpler when we get to visualization, we have '\n", + " 'provided an RVIz config file that will be loaded when we launch '\n", + " 'our package. This configuration file initializes RVIz with the '\n", + " 'proper settings so you can view the robot immediately once it '\n", + " 'launches. Create a directory namedrvizin the root of your '\n", + " 'project and a file namedurdf_config.rvizunder it. Place the '\n", + " 'following as the contents ofurdf_config.rviz',\n", + " 'filename': 'urdf_config.rviz',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, let us modify theCMakeLists.txtfile in the project root '\n", + " 'directory to include the files we just created during the '\n", + " 'package installation process. Add the following snippet '\n", + " 'toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\nbuild\\n.\\ninstall/setup.bash\\n',\n", + " 'context': 'We are now ready to build our project using colcon. Navigate to '\n", + " 'the project root and execute the following commands.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nsam_bot_description\\ndisplay.launch.py\\n',\n", + " 'context': 'After a successful build, execute the following commands to '\n", + " 'install the ROS 2 package and launch our project.',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '17\\n'\n", + " '\\n'\n", + " '18\\n'\n", + " '\\n'\n", + " '19\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '21\\n'\n", + " '\\n'\n", + " '22\\n'\n", + " '\\n'\n", + " '23\\n'\n", + " '\\n'\n", + " '24\\n'\n", + " '\\n'\n", + " '25\\n'\n", + " '26\\n'\n", + " '\\n'\n", + " '27\\n'\n", + " '\\n'\n", + " '28\\n'\n", + " '\\n'\n", + " '29\\n'\n", + " '\\n'\n", + " '30\\n'\n", + " '\\n'\n", + " '31\\n'\n", + " '\\n'\n", + " '32\\n'\n", + " '\\n'\n", + " '33\\n'\n", + " '34\\n'\n", + " '\\n'\n", + " '35\\n'\n", + " '\\n'\n", + " '36\\n'\n", + " '\\n'\n", + " '37\\n'\n", + " '\\n'\n", + " '38\\n'\n", + " '\\n'\n", + " '39\\n'\n", + " '',\n", + " 'context': 'Let us first define macros containing the inertial properties of '\n", + " 'the geometric primitives we used in our project. Place the '\n", + " 'snippet below after our constants section in the URDF:',\n", + " 'filename': 'if(BUILD_TESTING)',\n", + " 'language': 'unknown'},\n", + " {'code': '52\\n'\n", + " '\\n'\n", + " '53\\n'\n", + " '\\n'\n", + " '54\\n'\n", + " '\\n'\n", + " '55\\n'\n", + " '\\n'\n", + " '56\\n'\n", + " '\\n'\n", + " '57\\n'\n", + " '58\\n'\n", + " '',\n", + " 'context': 'Let us start by adding collision areas to ourbase_linkusing '\n", + " 'thetag. We will also be using the box_inertia macro '\n", + " 'we defined before to add some inertial properties to '\n", + " 'ourbase_link. Include the following code snippet '\n", + " 'withintag of base_link in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '83\\n'\n", + " '\\n'\n", + " '84\\n'\n", + " '\\n'\n", + " '85\\n'\n", + " '\\n'\n", + " '86\\n'\n", + " '\\n'\n", + " '87\\n'\n", + " '\\n'\n", + " '88\\n'\n", + " '\\n'\n", + " '89\\n'\n", + " '90\\n'\n", + " '',\n", + " 'context': 'Next, let us do the same for our wheel macros. Include the '\n", + " 'following code snippet within thetag '\n", + " 'of our wheel macros in our URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '114\\n'\n", + " '\\n'\n", + " '115\\n'\n", + " '\\n'\n", + " '116\\n'\n", + " '\\n'\n", + " '117\\n'\n", + " '\\n'\n", + " '118\\n'\n", + " '\\n'\n", + " '119\\n'\n", + " '\\n'\n", + " '120\\n'\n", + " '121\\n'\n", + " '',\n", + " 'context': 'Lastly, let us add the similar properties to our spherical '\n", + " 'caster wheels. Include the following in '\n", + " 'thetag of our caster wheel in the URDF.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Build your project and then launch RViz using the same commands '\n", + " 'in the previous section.',\n", + " 'filename': 'base_footprint',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Camera Calibration\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to obtain calibration parameters for monocular camera.\n", + "\n", + "## Requirements\n", + "1- Install Camera Calibration Parser, Camera Info Manager and Launch Testing Ament Cmake using operating system’s package manager:\n", + "2- Image Pipeline need to be built from source in your workspace with:\n", + "Also, make sure you have the following:\n", + "\n", + "## Tutorial Steps\n", + "1- Start a terminal in your GUI\n", + "2- Launch the ROS driver for your specific camera.\n", + "3- Make sure camera is publishing images over ROS. This can be tested by running:\n", + "4- This will show you all the topics published make sure that there is an image_raw topic /camera/image_raw. To confirm that its a real topic and actually publishing check topic hz:\n", + "5- Start the camera calibration node\n", + "6- In order to get a good calibration you will need to move the checkerboard around in the camera frame such that:\n", + "7- As the checkerboard is moved around the 4 bars on the calibration sidebar increases in length. When all then the 4 bars are green and enough data is available for calibration the CALIBRATE button will light up. Click it to see the results. It takes around the minute for calibration to take place.\n", + "8- After the calibration is completed the save and commit buttons light up. And you can also see the result in terminal.\n", + "9-Press the save button to see the result. Data is saved to “/tmp/calibrationdata.tar.gz”\n", + "11-In the folder images used for calibration are available and also “ost.yaml” and “ost.txt”. You can use the yaml file which contains the calibration parameters as directed by the camera driver.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'Camera\\n'\n", + " 'Name\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'c\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'camera_name\\n'\n", + " 'name\\n'\n", + " 'of\\n'\n", + " 'the\\n'\n", + " 'camera\\n'\n", + " 'to\\n'\n", + " 'appear\\n'\n", + " 'in\\n'\n", + " 'the\\n'\n", + " 'calibration\\n'\n", + " 'file\\n'\n", + " 'Chessboard\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " 'You\\n'\n", + " 'must\\n'\n", + " 'specify\\n'\n", + " 'one\\n'\n", + " 'or\\n'\n", + " 'more\\n'\n", + " 'chessboards\\n'\n", + " 'as\\n'\n", + " 'pairs\\n'\n", + " 'of\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " 'and\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " 'options\\n'\n", + " '.\\n'\n", + " '-\\n'\n", + " 'p\\n'\n", + " 'PATTERN\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'pattern\\n'\n", + " '=\\n'\n", + " 'PATTERN\\n'\n", + " 'calibration\\n'\n", + " 'pattern\\n'\n", + " 'to\\n'\n", + " 'detect\\n'\n", + " '-\\n'\n", + " \"'chessboard'\\n\"\n", + " ',\\n'\n", + " \"'circles'\\n\"\n", + " ',\\n'\n", + " \"'acircles'\\n\"\n", + " ',\\n'\n", + " \"'charuco'\\n\"\n", + " '-\\n'\n", + " 's\\n'\n", + " 'SIZE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'size\\n'\n", + " '=\\n'\n", + " 'SIZE\\n'\n", + " 'chessboard\\n'\n", + " 'size\\n'\n", + " 'as\\n'\n", + " 'NxM\\n'\n", + " ',\\n'\n", + " 'counting\\n'\n", + " 'interior\\n'\n", + " 'corners\\n'\n", + " '(\\n'\n", + " 'e\\n'\n", + " '.\\n'\n", + " 'g\\n'\n", + " '.\\n'\n", + " 'a\\n'\n", + " 'standard\\n'\n", + " 'chessboard\\n'\n", + " 'is\\n'\n", + " '7\\n'\n", + " 'x7\\n'\n", + " ')\\n'\n", + " '-\\n'\n", + " 'q\\n'\n", + " 'SQUARE\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'square\\n'\n", + " '=\\n'\n", + " 'SQUARE\\n'\n", + " 'chessboard\\n'\n", + " 'square\\n'\n", + " 'size\\n'\n", + " 'in\\n'\n", + " 'meters\\n'\n", + " 'ROS\\n'\n", + " 'Communication\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'approximate\\n'\n", + " '=\\n'\n", + " 'APPROXIMATE\\n'\n", + " 'allow\\n'\n", + " 'specified\\n'\n", + " 'slop\\n'\n", + " '(\\n'\n", + " 'in\\n'\n", + " 'seconds\\n'\n", + " ')\\n'\n", + " 'when\\n'\n", + " 'pairing\\n'\n", + " 'images\\n'\n", + " 'from\\n'\n", + " 'unsynchronized\\n'\n", + " 'stereo\\n'\n", + " 'cameras\\n'\n", + " '--\\n'\n", + " 'no\\n'\n", + " '-\\n'\n", + " 'service\\n'\n", + " '-\\n'\n", + " 'check\\n'\n", + " 'disable\\n'\n", + " 'check\\n'\n", + " 'for\\n'\n", + " 'set_camera_info\\n'\n", + " 'services\\n'\n", + " 'at\\n'\n", + " 'startup\\n'\n", + " 'Calibration\\n'\n", + " 'Optimizer\\n'\n", + " 'Options\\n'\n", + " ':\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'principal\\n'\n", + " '-\\n'\n", + " 'point\\n'\n", + " 'fix\\n'\n", + " 'the\\n'\n", + " 'principal\\n'\n", + " 'point\\n'\n", + " 'at\\n'\n", + " 'the\\n'\n", + " 'image\\n'\n", + " 'center\\n'\n", + " '--\\n'\n", + " 'fix\\n'\n", + " '-\\n'\n", + " 'aspect\\n'\n", + " '-\\n'\n", + " 'ratio\\n'\n", + " 'enforce\\n'\n", + " 'focal\\n'\n", + " 'lengths\\n'\n", + " '(\\n'\n", + " 'fx\\n'\n", + " ',\\n'\n", + " 'fy\\n'\n", + " ')\\n'\n", + " 'are\\n'\n", + " 'equal\\n'\n", + " '--\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'tangent\\n'\n", + " '-\\n'\n", + " 'dist\\n'\n", + " 'set\\n'\n", + " 'tangential\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " '(\\n'\n", + " 'p1\\n'\n", + " ',\\n'\n", + " 'p2\\n'\n", + " ')\\n'\n", + " 'to\\n'\n", + " 'zero\\n'\n", + " '-\\n'\n", + " 'k\\n'\n", + " 'NUM_COEFFS\\n'\n", + " ',\\n'\n", + " '--\\n'\n", + " 'k\\n'\n", + " '-\\n'\n", + " 'coefficients\\n'\n", + " '=\\n'\n", + " 'NUM_COEFFS\\n'\n", + " 'number\\n'\n", + " 'of\\n'\n", + " 'radial\\n'\n", + " 'distortion\\n'\n", + " 'coefficients\\n'\n", + " 'to\\n'\n", + " 'use\\n'\n", + " '(\\n'\n", + " 'up\\n'\n", + " 'to\\n'\n", + " '6\\n'\n", + " ',\\n'\n", + " 'default\\n'\n", + " '2\\n'\n", + " ')\\n'\n", + " '--\\n'\n", + " 'disable_calib_cb_fast_check\\n'\n", + " 'uses\\n'\n", + " 'the\\n'\n", + " 'CALIB_CB_FAST_CHECK\\n'\n", + " 'flag\\n'\n", + " 'for\\n'\n", + " 'findChessboardCorners\\n'\n", + " 'This\\n'\n", + " 'will\\n'\n", + " 'open\\n'\n", + " 'a\\n'\n", + " 'calibration\\n'\n", + " 'window\\n'\n", + " 'which\\n'\n", + " 'highlight\\n'\n", + " 'the\\n'\n", + " 'checkerboard\\n'\n", + " '.',\n", + " 'context': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'filename': 'ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Groot - Interacting with Behavior Trees\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Grootis the companion application of theBehaviorTree.CPPlibrary used to create, edit, and visualize behavior trees.\n", + "Behavior Trees are deeply integrated into Nav2, used as the main method of orchestrating task server logic across a complex navigation and autonomy stack.\n", + "Behavior Trees, in short BTs, consist of many nodes completing different tasks and control the flow of logic, similar to a Hierarchical or Finite State Machine, but organized in a tree structure.\n", + "These nodes are of types:Action,Condition,Control, orDecorator, and are described in more detail inNavigation ConceptsandBehaviorTree.CPP.\n", + "Writing a New Behavior Tree Pluginoffers a well written example of creating a simpleActionnode if creating new BT nodes is of interest. This tutorial will focus solely on launching Groot, visualizing a Behavior Tree, and modifying that tree for a given customization, assuming a library of BT nodes. Luckily, Nav2 provides a robust number of BT nodes for your use out of the box, enumerated inNavigation Plugins.\n", + "A BT configuration file in BehaviorTree.CPP is an XML file. This is used to dynamically load the BT node plugins at run-time from the appropriate libraries mapped to their names. The XML format is definedin detail here. Therefore, Groot needs to have a list of nodes it has access to and important metadata about them like their type and ports (or parameters). We refer to this as the “palette” of nodes later in the tutorial.\n", + "In the video above you can see Groot side-by-side with RVIz and a test platform 100% equipped with ROS-enabled hardware from SIEMENS.\n", + "Groot not only displays the current Behavior Tree while the robot is operating. Note: Before ROS 2 Humble, live Groot behavior tree monitoring during execution was supported in Nav2. This was removed due to buggy support in BT.CPP / Groot for changing behavior trees on the fly, seeGalactic to Humblefor more details.\n", + "\n", + "## Visualize Behavior Trees\n", + "To display a Behavior Tree like that inFigure 3, we will first start the Groot executable.\n", + "Out of the box, Groot can only display Behavior Trees and nodes that are from the defaults in BT.CPP, since it does not know anything about Nav2 or your other projects.\n", + "Therefore, we must point Groot to our palette, or index, of Nav2 / custom behavior tree nodes:\n", + "If you select the default treenavigate_w_replanning_and_recovery.xml, then a Groot editor should look likeFigure 3.\n", + "\n", + "## Edit Behavior Trees\n", + "Now that you have a Nav2 BT open in Groot in editor mode, you should be able to trivially modify it using the GUI.\n", + "Starting from a screen like that shown inFigure 3, you can pull in new nodes from the side panel to add them to the workspace.\n", + "You may then connect the nodes using a “drag and drop” motion between the node’s input and output ports to assemble the new nodes into the tree.\n", + "If you select a given node, you can change metadata about it such as its name or values of parameterizable ports. When you’re done modifying, simply save the new configuration file and use that on your robot the next time!\n", + "\n", + "## Adding A Custom Node\n", + "Each node in the behavior tree holds a specialized function.\n", + "Sometimes, its useful to create new nodes and add them to your palette during the design process - perhaps before the implementations themselves exist.\n", + "This helps designers abstract away the implementation specifics of the nodes from the higher level logic of the tree itself and how they’d like to interact with a given node (e.g. type, ports, etc).\n", + "Within Groot, you may create new custom nodes to add to your tree and export these new nodes back to your palette.\n", + "Implementing the node itself needs to be done separately from Groot, which is described inWriting a New Behavior Tree Plugin.\n", + "Creating a new custom node can be started by clicking the orange marked icon inFigure 4, while Groot is in Editor mode.\n", + "This should load a new window, similar toFigure 5.\n", + "In this new window, it asks you to fill in the metadata about this new node, in order to create it.\n", + "It will ask you for standard information such as name (green box), type of node (orange box), and any optional ports for parameterization or access to blackboard variables (blue box).\n", + "After completing, selectOKinFigure 5, the new custom node should appear in blue in theTreeNode Paletteas inFigure 6.\n", + "Before starting to create a new BT based on the new custom nodes, it is recommend to export the newly created nodes to save in case of Groot crashing.\n", + "This can be performed with the icon highlighted in green fromFigure 6.\n", + "The resulting XML output from the node created inFigure 5can be seen below.\n", + "You can see more examples inNav2’s BT Node Palette XML.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'coffee\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Sense\\n'\n", + " 'of\\n'\n", + " 'life\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rolling\\n'\n", + " 'target\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Before starting to create a new BT based on the new custom '\n", + " 'nodes, it is recommend to export the newly created nodes to save '\n", + " 'in case of Groot crashing.\\n'\n", + " 'This can be performed with the icon highlighted in green '\n", + " 'fromFigure 6.\\n'\n", + " 'The resulting XML output from the node created inFigure 5can be '\n", + " 'seen below.\\n'\n", + " 'You can see more examples inNav2’s BT Node Palette XML.',\n", + " 'filename': 'Action',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Getting Involved\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Getting Involved\n", + "If you’re interested in getting involved in Navigation 2, first of all, welcome!\n", + "We encourage everyone to get involved from students, to junior developers, to senior developers, and executives.\n", + "There’s something to do for everyone from bug fixes, to feature development, new algorithms, and refactoring.\n", + "All ROS 2 TSC Working Groups have their meetings on theworking group calendar.\n", + "Here, you can find the date and time of the Navigation2 working group meeting. Make sure you’re checking in your local timezone.\n", + "From this calendar, you can add yourself to the event so it will appear on your google calendar and get the event link to the call through Google Hangouts.\n", + "We encourage everyone interested to come to the meeting to introduce yourself, your project, and see what everyone is working on.\n", + "Further,ROS Discourseis a good place to follow larger discussions happening in the community and announcements. This isnotthe correct place to post questions or ask for assistance. Please visitROS Answersfor Q&A.\n", + "Lastly, we have aCommunity Slackwhere we chat in real-time about topics in public channels or sidebar maintainers on individual projects via PMs. If you’re interested in contributing to Nav2, this is a great place to join!\n", + "If you’re looking to contribute code or bugs, please see the Process section below.\n", + "Over time, for developers that have an interest and have shown technical competence in an area of the stack, we elevate developers to a maintainers status.\n", + "That allows push rights to our protected branches, first-reviewers rights, and getting your name onAbout and Contact.\n", + "There currently is not a clear process for getting to be a maintainer, but if you’ve been involved and contributing over a duration of several months, you may be a good candidate and should email the project lead listed onAbout and Contact.\n", + "\n", + "## Process\n", + "After you’ve introduced yourself in a working group meeting (recommended, not required), you’re ready to get started!\n", + "We recommend a typical open-source project flow and value detail and transparency.\n", + "If you commit to something and need to pull back, say so.\n", + "We all know priorities change and appreciate the heads up so that task can go into the open queue of tasks.\n", + "The process is simple and is as follow:\n", + "Note: We take code quality seriously and strive for high-quality and consistent code.\n", + "We make use of the linting and static analysis tools provided in ROS 2 (ament_cpplint,ament_uncrustify,ament_cppcheck, etc).\n", + "All PRs are built in CI with the appropriate ROS distributions and run through a set of unit and system level tests including static analysis.\n", + "You can see the results of these tests in the pull request.\n", + "It is expected for feature development for tests to cover this work to be added.\n", + "If any documentation must be updated due to your changes, that should be included in your pull request.\n", + "\n", + "## Licensing\n", + "Licensing is very important to open source projects. It helps ensure the\n", + "software continues to be available under the terms that the author\n", + "desired.\n", + "Because much of the source code is ported from other ROS 1 projects, each\n", + "package has it’s own license. Contributions should be made under the predominant\n", + "license of that package. Entirely new packages should be made available under\n", + "theApache 2.0 license.\n", + "A license tells you what rights you have as a developer, as provided by\n", + "the copyright holder. It is important that the contributor fully\n", + "understands the licensing rights and agrees to them. Sometimes the\n", + "copyright holder isn’t the contributor, such as when the contributor is\n", + "doing work on behalf of a company.\n", + "If for some reason Apache 2.0 or BSD licenses are not appropriate for your work, please get in contact with a project maintainer and discuss your concerns or requirements.\n", + "We may consider special exceptions for exceptional work, within reason (we will not accept any licenses that makes it unsuitable for commercial use).\n", + "\n", + "## Developer Certification of Origin (DCO)\n", + "To make a good faith effort to ensure licensing criteria are met,\n", + "Nav2 encourages the Developer Certificate of Origin (DCO) process\n", + "to be followed.\n", + "The DCO is an attestation attached to every contribution made by a\n", + "developer. In the commit message of the contribution, (described more\n", + "fully later in this document), the developer simply adds aSigned-off-bystatement and thereby agrees to the DCO.\n", + "In practice, its easier to justgitcommit-s-m\"commitmessage.\".\n", + "Where-sadds this automatically.\n", + "If you forgot to add this to a commit, it is easy to append via:gitcommit--amend-s.\n", + "When a developer submits a patch, it is a commitment that the\n", + "contributor has the right to submit the patch per the license. The DCO\n", + "agreement is shown below and athttp://developercertificate.org/.\n", + "\n", + "Code Blocks:\n", + "[{'code': \"Developer's Certificate of Origin 1.1\\n\"\n", + " '\\n'\n", + " 'By making a contribution to this project, I certify that:\\n'\n", + " '\\n'\n", + " '(a) The contribution was created in whole or in part by me and I\\n'\n", + " ' have the right to submit it under the open source license\\n'\n", + " ' indicated in the file; or\\n'\n", + " '\\n'\n", + " '(b) The contribution is based upon previous work that, to the\\n'\n", + " ' best of my knowledge, is covered under an appropriate open\\n'\n", + " ' source license and I have the right under that license to\\n'\n", + " ' submit that work with modifications, whether created in whole\\n'\n", + " ' or in part by me, under the same open source license (unless\\n'\n", + " ' I am permitted to submit under a different license), as\\n'\n", + " ' Indicated in the file; or\\n'\n", + " '\\n'\n", + " '(c) The contribution was provided directly to me by some other\\n'\n", + " ' person who certified (a), (b) or (c) and I have not modified\\n'\n", + " ' it.\\n'\n", + " '\\n'\n", + " '(d) I understand and agree that this project and the contribution\\n'\n", + " ' are public and that a record of the contribution (including\\n'\n", + " ' all personal information I submit with it, including my\\n'\n", + " ' sign-off) is maintained indefinitely and may be redistributed\\n'\n", + " ' consistent with this project or the open source license(s)\\n'\n", + " ' involved.\\n',\n", + " 'context': 'When a developer submits a patch, it is a commitment that the\\n'\n", + " 'contributor has the right to submit the patch per the license. '\n", + " 'The DCO\\n'\n", + " 'agreement is shown below and athttp://developercertificate.org/.',\n", + " 'filename': 'gitcommit--amend-s',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: AreErrorCodesPresent\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "Error codes to check are defined in another port.\n", + "Error codes to check are defined to be 101, 107 and 119.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Error codes to check are defined in another port.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'Error codes to check are defined to be 101, 107 and 119.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Planner and Controller Servers\n", + "Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice.\n", + "The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment.\n", + "The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station.\n", + "As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server.\n", + "\n", + "## Selecting the Algorithm Plugins\n", + "In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server.\n", + "\n", + "## Planner Server\n", + "The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility.\n", + "As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments.\n", + "One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots.\n", + "Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds.\n", + "There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration.\n", + "\n", + "## Summary\n", + "\n", + "\n", + "## Example Configuration\n", + "An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Controller Server\n", + "The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity.\n", + "TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint.\n", + "Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots.\n", + "Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots.\n", + "The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots.\n", + "\n", + "## Summary\n", + "All of these algorithms work for both circular and non-circular robots.\n", + "\n", + "## Example Configuration\n", + "Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Non-circular Differential, Non-circular Omnidirectional',\n", + " 'filename': 'SmacLatticeplanner',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'All of these algorithms work for both circular and non-circular '\n", + " 'robots.',\n", + " 'filename': 'TrajectoryGenerationplugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Development Guides\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Build and Install\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Install\n", + "Nav2 and its dependencies are released as binaries.\n", + "You may install it via the following to get the latest stable released version:\n", + "\n", + "## For Iron and Older\n", + "\n", + "\n", + "## For Jazzy and Newer\n", + "\n", + "\n", + "## Build\n", + "There are a few ways to build Nav2 using:\n", + "\n", + "## Released Distribution Binaries\n", + "To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool.\n", + "Once your environment is setup, clone the repo, install all dependencies, and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations!\n", + "\n", + "## Rolling Development Source\n", + "Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages.\n", + "Nav2 does not currently release binaries on rolling, so it must be build from source.\n", + "Once your environment is setup, clone the repo and build the workspace:\n", + "You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe\n", + "to ignore the rosdep error of from the missingslam_toolboxkey.\n", + "\n", + "## Docker Container Images\n", + "Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions.\n", + "Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo:\n", + "Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process.\n", + "\n", + "## Generate Doxygen\n", + "Rundoxygenin the root of the Nav2 repository.\n", + "It will generate a/doc/*directory containing the documentation.\n", + "The documentation entrypoint in a browser is index.html.\n", + "\n", + "## Help\n", + "Build Troubleshooting Guide\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-turtlebot3*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-navigation2\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-bringup\\n'\n", + " '\\\\\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-nav2-minimal-tb*\\n',\n", + " 'context': 'Nav2 and its dependencies are released as binaries.\\n'\n", + " 'You may install it via the following to get the latest stable '\n", + " 'released version:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " '$ROS_DISTRO\\n'\n", + " './src/navigation2\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'The branch naming schema for Nav2 is organized by ROS distro, '\n", + " 'while the default branch for Rolling ismain.',\n", + " 'filename': 'main',\n", + " 'language': 'unknown'},\n", + " {'code': 'source\\n'\n", + " '/install/setup.bash\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/nav2_ws/src\\n'\n", + " '&&\\n'\n", + " 'cd\\n'\n", + " '~/nav2_ws\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/navigation2\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " './src/nav2_minimal_turtlebot_simulation\\n'\n", + " 'rosdep\\n'\n", + " 'install\\n'\n", + " '-r\\n'\n", + " '-y\\n'\n", + " '\\\\\\n'\n", + " '--from-paths\\n'\n", + " './src\\n'\n", + " '\\\\\\n'\n", + " '--ignore-src\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '\\\\\\n'\n", + " '--symlink-install\\n',\n", + " 'context': 'Once your environment is setup, clone the repo and build the '\n", + " 'workspace:',\n", + " 'filename': 'source~/nav2_ws/install/setup.bash',\n", + " 'language': 'unknown'},\n", + " {'code': 'export\\n'\n", + " 'ROS_DISTRO\\n'\n", + " '=\\n'\n", + " 'rolling\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2.git\\n'\n", + " '--branch\\n'\n", + " 'main\\n'\n", + " 'docker\\n'\n", + " 'build\\n'\n", + " '--tag\\n'\n", + " 'navigation2:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'FROM_IMAGE\\n'\n", + " '=\\n'\n", + " 'ros:\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '\\\\\\n'\n", + " '--build-arg\\n'\n", + " 'OVERLAY_MIXINS\\n'\n", + " '=\\n'\n", + " '\"release ccache lld\"\\n'\n", + " '\\\\\\n'\n", + " '--cache-from\\n'\n", + " 'ghcr.io/ros-navigation/navigation2:main\\n'\n", + " '\\\\\\n'\n", + " './navigation2\\n',\n", + " 'context': 'Once your system is setup, you can build the Nav2 Dockerfile '\n", + " 'from the root of the repo:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: First-Time Robot Setup Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Coverage Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'coverage_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'action_server_result_timeout\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'coordinates_in_cartesian_frame\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'robot_width\\n'\n", + " ':\\n'\n", + " '2.1\\n'\n", + " 'operation_width\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'min_turning_radius\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'linear_curv_change\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'default_allow_overlap\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'default_headland_width\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'default_path_continuity_type\\n'\n", + " ':\\n'\n", + " '\"CONTINUOUS\"\\n'\n", + " 'default_path_type\\n'\n", + " ':\\n'\n", + " '\"DUBINS\"\\n'\n", + " 'default_route_type\\n'\n", + " ':\\n'\n", + " '\"BOUSTROPHEDON\"\\n'\n", + " 'default_swath_angle_type\\n'\n", + " ':\\n'\n", + " '\"BRUTE_FORCE\"\\n'\n", + " 'default_swath_type\\n'\n", + " ':\\n'\n", + " '\"LENGTH\"\\n'\n", + " 'default_turn_point_distance\\n'\n", + " ':\\n'\n", + " '0.1',\n", + " 'context': 'Foropennav_row_coverage, whether to reorder the parsed rows in '\n", + " 'the order of their``id``s.',\n", + " 'filename': 'opennav_row_coverage',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Eloquent to Foxy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## General\n", + "The lifecycle manager was split into 2 unique lifecycle managers.\n", + "They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager.\n", + "This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation.\n", + "It also reduces the redundant code innav2_bringup.\n", + "The lifecycle manager also now containsBondconnections to each lifecycle server.\n", + "This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety.\n", + "This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details.\n", + "A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues.\n", + "As a result, a behavior tree is created for each navigation request rather than resetting an existing tree.\n", + "The creation of this tree will add a small amount of latency.\n", + "Proposals to reduce this latency will be considered before the next release.\n", + "\n", + "## Server Updates\n", + "All plugin servers (controller, planner, recovery) now supports the use of multiple plugins.\n", + "This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case.\n", + "Each server defines a parameter where the list of names for the plugins to be loaded can be defined.\n", + "The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list.\n", + "Each name in the plugin parameter list is expected to have thepluginparameter defined.\n", + "An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined:\n", + "FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner.\n", + "Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace.\n", + "This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names.\n", + "DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information.\n", + "Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization.\n", + "This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in.\n", + "E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter.\n", + "All plugins will be expected to look up parameters in the namespace of its given name.\n", + "\n", + "## New Plugins\n", + "Many new behavior tree nodes were added.\n", + "These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3.\n", + "The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "\n", + "## Map Server Re-Work\n", + "map_saverwas re-worked and divided into 2 parts: CLI and server.\n", + "CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality.\n", + "Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file.\n", + "map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future.\n", + "Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started.\n", + "map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead.\n", + "Please refer to theoriginal GitHub ticketandMap Server READMEfor more information.\n", + "\n", + "## New Particle Filter Messages\n", + "New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight.\n", + "AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray.\n", + "See here for more information.\n", + "\n", + "## Selection of Behavior Tree in each navigation action\n", + "TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used.\n", + "This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784.\n", + "\n", + "## FollowPoint Capability\n", + "A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers.\n", + "This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859.\n", + "\n", + "## New Costmap Layer\n", + "The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer\". It uses the same\n", + "probabilistic model as theROS1layer as well as much of the\n", + "same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ',\\n'\n", + " '\"DynamicFollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core/DWBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'DynamicFollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"teb_local_planner/TEBLocalPlanner\"\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.5',\n", + " 'context': 'An example:controller_serverdefines the '\n", + " 'parametercontroller_pluginswhere a list of plugin names can be '\n", + " 'defined:',\n", + " 'filename': 'controller_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PathLongerOnApproach\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Length multiplication factor to check if the path is '\n", + " 'significantly longer.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: SimpleProgressChecker\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_controller plugin name defined in theprogress_checker_plugin_idparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Galactic to Humble\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Major improvements to Smac Planners\n", + "The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality.\n", + "Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike.\n", + "Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference).\n", + "\n", + "## Simple (Python) Commander\n", + "This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API:\n", + "The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior.\n", + "\n", + "## Reduce Nodes and Executors\n", + "In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance.\n", + "This functionality has been discussed inthe ticket #816, and carried out in\n", + "\n", + "## API Change for nav2_core\n", + "PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>).\n", + "Use of shared pointer references meant that the shared pointer counter was never incremented.\n", + "\n", + "## Extending the BtServiceNode to process Service-Results\n", + "This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here).\n", + "Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation.\n", + "The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed.\n", + "The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example.\n", + "The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully.\n", + "\n", + "## Including new Rotation Shim Controller Plugin\n", + "This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking.\n", + "The Rotation Shim Controller is suitable for:\n", + "\n", + "## Spawning the robot in Gazebo\n", + "This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo.\n", + "Note that\n", + "\n", + "## Recovery Behavior Timeout\n", + "Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time.\n", + "\n", + "## New parameteruse_final_approach_orientationfor the 3 2D planners\n", + "Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation.\n", + "For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right)\n", + "\n", + "## SmacPlanner2D and Theta*: fix goal orientation being ignored\n", + "This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0).\n", + "\n", + "## SmacPlanner2D, NavFn and Theta*: fix small path corner cases\n", + "This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose.\n", + "\n", + "## Change and fix behavior of dynamic parameter change detection\n", + "Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name.\n", + "\n", + "## Dynamic Parameters\n", + "Newly added dynamic parameters to:\n", + "\n", + "## BT Action Nodes Exception Changes\n", + "When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to.\n", + "\n", + "## BT Navigator Groot Multiple Navigators\n", + "This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2.\n", + "There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation.\n", + "\n", + "## Removed Kinematic Limiting in RPP\n", + "The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior.\n", + "\n", + "## Added Smoother Task Server\n", + "A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future.\n", + "\n", + "## Removed Use Approach Velocity Scaling Param in RPP\n", + "The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements.\n", + "\n", + "## Refactored AMCL motion models as plugins\n", + "This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code.\n", + "\n", + "## Dropping Support for Live Groot Monitoring of Nav2\n", + "It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration.\n", + "So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly.\n", + "\n", + "## Replanning Only if Path is Invalid\n", + "This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT.\n", + "\n", + "## Fix CostmapLayer clearArea invert param logic\n", + "This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions.\n", + "\n", + "## Dynamic Composition\n", + "This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False.\n", + "Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil:\n", + "The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes.\n", + "\n", + "## BT Cancel Node\n", + "This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait.\n", + "\n", + "## BT PathLongerOnApproach Node\n", + "In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan:\n", + "Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds:\n", + "Obstacle clears and you can see the robot pass through the (could have been ideally the) same path:\n", + "\n", + "## BT TruncatePathLocal Node\n", + "In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers\n", + "\n", + "## Constrained Smoother\n", + "Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius\n", + "\n", + "## Replanning at a Constant Rate and if the Path is Invalid\n", + "This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid.\n", + "To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate.\n", + "\n", + "## Euclidean Distance 2D\n", + "This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z).\n", + "This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem.\n", + "\n", + "## Recovery To Behavior\n", + "This PR 2867renames the nav2_recoveries to nav2_behaviors.\n", + "In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors.\n", + "In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors.\n", + "\n", + "## Respawn Support in Launch and Lifecycle Manager\n", + "PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it.\n", + "That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically.\n", + "\n", + "## New Nav2 Velocity Smoother\n", + "PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Goal Checker API Changed\n", + "PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass.\n", + "The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin.\n", + "\n", + "## Added Assisted Teleop\n", + "PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'def\\n'\n", + " 'main\\n'\n", + " '():\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'init\\n'\n", + " '()\\n'\n", + " 'navigator\\n'\n", + " '=\\n'\n", + " 'BasicNavigator\\n'\n", + " '()\\n'\n", + " \"# Set our demo's initial pose\\n\"\n", + " 'initial_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'setInitialPose\\n'\n", + " '(\\n'\n", + " 'initial_pose\\n'\n", + " ')\\n'\n", + " '# Wait for navigation to fully activate\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'waitUntilNav2Active\\n'\n", + " '()\\n'\n", + " '# Go to our demos first goal pose\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'PoseStamped\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'populate\\n'\n", + " 'pose\\n'\n", + " '...\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'goToPose\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'isTaskComplete\\n'\n", + " '():\\n'\n", + " 'feedback\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getFeedback\\n'\n", + " '()\\n'\n", + " '...\\n'\n", + " 'do\\n'\n", + " 'something\\n'\n", + " 'with\\n'\n", + " 'feedback\\n'\n", + " '...\\n'\n", + " '# Basic navigation timeout\\n'\n", + " 'if\\n'\n", + " 'Duration\\n'\n", + " '.\\n'\n", + " 'from_msg\\n'\n", + " '(\\n'\n", + " 'feedback\\n'\n", + " '.\\n'\n", + " 'navigation_time\\n'\n", + " ')\\n'\n", + " '>\\n'\n", + " 'Duration\\n'\n", + " '(\\n'\n", + " 'seconds\\n'\n", + " '=\\n'\n", + " '600.0\\n'\n", + " '):\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'cancelNav\\n'\n", + " '()\\n'\n", + " 'result\\n'\n", + " '=\\n'\n", + " 'navigator\\n'\n", + " '.\\n'\n", + " 'getResult\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'SUCCEEDED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal succeeded!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'CANCELED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal was canceled!'\\n\"\n", + " ')\\n'\n", + " 'elif\\n'\n", + " 'result\\n'\n", + " '==\\n'\n", + " 'TaskResult\\n'\n", + " '.\\n'\n", + " 'FAILED\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Goal failed!'\\n\"\n", + " ')',\n", + " 'context': 'This PR 2411introduces a new package to Nav2, called '\n", + " 'thenav2_simple_commander. It is a set of functions in an '\n", + " 'object,BasicNavigator, which can be used to build Nav2-powered '\n", + " 'autonomy tasks in Python3 without concerning yourself with the '\n", + " 'Nav2, ROS 2, or Action server details. It contains a simple API '\n", + " 'taking common types (primarilyPoseStamped) and handles all of '\n", + " 'the implementation details behind the hood. For example, this is '\n", + " 'a simple navigation task using this API:',\n", + " 'filename': 'PoseStamped',\n", + " 'language': 'unknown'},\n", + " {'code': '/**\\n'\n", + " '* @brief Function to perform some user-defined operation upon '\n", + " 'successful\\n'\n", + " '* completion of the service. Could put a value on the blackboard.\\n'\n", + " '* @param response can be used to get the result of the service call '\n", + " 'in the BT Node.\\n'\n", + " '* @return BT::NodeStatus Returns SUCCESS by default, user may '\n", + " 'override to return another value\\n'\n", + " '*/\\n'\n", + " 'virtual\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " 'on_completion\\n'\n", + " '(\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'typename\\n'\n", + " 'ServiceT\\n'\n", + " '::\\n'\n", + " 'Response\\n'\n", + " '>\\n'\n", + " '/*response*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeStatus\\n'\n", + " '::\\n'\n", + " 'SUCCESS\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'This PR 2481andPR 2992addressthe ticketandthis ticketand adds a '\n", + " 'virtualon_completion()function to theBtServiceNodeclass (can be '\n", + " 'found here).\\n'\n", + " 'Similar to the already existing '\n", + " 'virtualon_wait_for_result()function, it can be overwritten in '\n", + " 'the child class to react to a respective event with some '\n", + " 'user-defined operation.\\n'\n", + " 'The addedon_completion()function will be called after the '\n", + " 'service interaction of theBtServiceNodehas been successfully '\n", + " 'completed.',\n", + " 'filename': 'BtServiceNode',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Controller Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own controllerplugin.\n", + "In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper.\n", + "It is recommended you go through it.\n", + "Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack.\n", + "You can find the source code matching this tutorialhere.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Controller Plugin\n", + "We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository\n", + "as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin.\n", + "Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a\n", + "set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands.\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands.\n", + "In controllers,configure()method must set member variables from ROS parameters and perform any initialization required.\n", + "Here,plugin_name_+\".desired_linear_vel\"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller.\n", + "Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name.\n", + "Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet.\n", + "For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”,\n", + "we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters.\n", + "We will see more on this when we discuss the parameters file (or params file).\n", + "The passed-in arguments are stored in member variables so that they can be used at a later stage if needed.\n", + "InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into\n", + "the frame of the robot and then store this transformed global path for later use.\n", + "The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose.\n", + "The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used.\n", + "In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible.\n", + "This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path.\n", + "The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty.\n", + "\n", + "## 2- Exporting the controller plugin\n", + "Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run Pure Pursuit Controller plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that controller will make the robot follow the global path.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'void\\n'\n", + " 'PurePursuitController::configure\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " '&\\n'\n", + " 'parent\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'tf2_ros\\n'\n", + " '::\\n'\n", + " 'Buffer\\n'\n", + " '>\\n'\n", + " 'tf\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Costmap2DROS\\n'\n", + " '>\\n'\n", + " 'costmap_ros\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'node_\\n'\n", + " '=\\n'\n", + " 'parent\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'node_\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'costmap_ros_\\n'\n", + " '=\\n'\n", + " 'costmap_ros\\n'\n", + " ';\\n'\n", + " 'tf_\\n'\n", + " '=\\n'\n", + " 'tf\\n'\n", + " ';\\n'\n", + " 'plugin_name_\\n'\n", + " '=\\n'\n", + " 'name\\n'\n", + " ';\\n'\n", + " 'logger_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '();\\n'\n", + " 'clock_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_clock\\n'\n", + " '();\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.2\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.4\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '1.0\\n'\n", + " '));\\n'\n", + " 'declare_parameter_if_not_declared\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " '0.1\\n'\n", + " '));\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".desired_linear_vel\"\\n'\n", + " ',\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".lookahead_dist\"\\n'\n", + " ',\\n'\n", + " 'lookahead_dist_\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".max_angular_vel\"\\n'\n", + " ',\\n'\n", + " 'max_angular_vel_\\n'\n", + " ');\\n'\n", + " 'double\\n'\n", + " 'transform_tolerance\\n'\n", + " ';\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'plugin_name_\\n'\n", + " '+\\n'\n", + " '\".transform_tolerance\"\\n'\n", + " ',\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " 'transform_tolerance_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Duration\\n'\n", + " '::\\n'\n", + " 'from_seconds\\n'\n", + " '(\\n'\n", + " 'transform_tolerance\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'In controllers,configure()method must set member variables from '\n", + " 'ROS parameters and perform any initialization required.',\n", + " 'filename': 'configure()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'PurePursuitController::setPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '&\\n'\n", + " 'path\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " \"// Transform global path into the robot's frame\\n\"\n", + " 'global_plan_\\n'\n", + " '=\\n'\n", + " 'transformGlobalPlan\\n'\n", + " '(\\n'\n", + " 'path\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'InsetPlan()method, we receive the updated global path for the '\n", + " 'robot to follow. In our example, we transform the received '\n", + " 'global path into\\n'\n", + " 'the frame of the robot and then store this transformed global '\n", + " 'path for later use.',\n", + " 'filename': 'setPlan()',\n", + " 'language': 'unknown'},\n", + " {'code': 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'PurePursuitController::computeVelocityCommands\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'pose\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Twist\\n'\n", + " '&\\n'\n", + " 'velocity\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'GoalChecker\\n'\n", + " '*\\n'\n", + " '/*goal_checker*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Find the first pose which is at a distance greater than the '\n", + " 'specified lookahead distance\\n'\n", + " 'auto\\n'\n", + " 'goal_pose\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'find_if\\n'\n", + " '(\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'begin\\n'\n", + " '(),\\n'\n", + " 'global_plan_\\n'\n", + " '.\\n'\n", + " 'poses\\n'\n", + " '.\\n'\n", + " 'end\\n'\n", + " '(),\\n'\n", + " '[\\n'\n", + " '&\\n'\n", + " '](\\n'\n", + " 'const\\n'\n", + " 'auto\\n'\n", + " '&\\n'\n", + " 'global_plan_pose\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'hypot\\n'\n", + " '(\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'global_plan_pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ')\\n'\n", + " '>=\\n'\n", + " 'lookahead_dist_\\n'\n", + " ';\\n'\n", + " '})\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ';\\n'\n", + " 'double\\n'\n", + " 'linear_vel\\n'\n", + " ',\\n'\n", + " 'angular_vel\\n'\n", + " ';\\n'\n", + " '// If the goal pose is in front of the robot then compute the '\n", + " 'velocity using the pure pursuit algorithm\\n'\n", + " '// else rotate with the max angular velocity until the goal pose is '\n", + " 'in front of the robot\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '>\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'curvature\\n'\n", + " '=\\n'\n", + " '2.0\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '/\\n'\n", + " '(\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '+\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " '*\\n'\n", + " 'goal_pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'desired_linear_vel_\\n'\n", + " '*\\n'\n", + " 'curvature\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'linear_vel\\n'\n", + " '=\\n'\n", + " '0.0\\n'\n", + " ';\\n'\n", + " 'angular_vel\\n'\n", + " '=\\n'\n", + " 'max_angular_vel_\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '// Create and publish a TwistStamped message with the desired '\n", + " 'velocity\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'TwistStamped\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " '=\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'frame_id\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'header\\n'\n", + " '.\\n'\n", + " 'stamp\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'linear\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " '=\\n'\n", + " 'linear_vel\\n'\n", + " ';\\n'\n", + " 'cmd_vel\\n'\n", + " '.\\n'\n", + " 'twist\\n'\n", + " '.\\n'\n", + " 'angular\\n'\n", + " '.\\n'\n", + " 'z\\n'\n", + " '=\\n'\n", + " 'max\\n'\n", + " '(\\n'\n", + " '-1.0\\n'\n", + " '*\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " '),\\n'\n", + " 'min\\n'\n", + " '(\\n'\n", + " 'angular_vel\\n'\n", + " ',\\n'\n", + " 'abs\\n'\n", + " '(\\n'\n", + " 'max_angular_vel_\\n'\n", + " ')));\\n'\n", + " 'return\\n'\n", + " 'cmd_vel\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The computation for the desired velocity happens in '\n", + " 'thecomputeVelocityCommands()method. It is used to calculate the '\n", + " 'desired velocity command given the current velocity and pose.\\n'\n", + " 'The third argument - is a pointer to thenav2_core::GoalChecker, '\n", + " 'that checks whether a goal has been reached. In our example, '\n", + " 'this won’t be used.\\n'\n", + " 'In the case of pure pursuit, the algorithm computes velocity '\n", + " 'commands such that the robot tries to follow the global path as '\n", + " 'closely as possible.\\n'\n", + " 'This algorithm assumes a constant linear velocity and computes '\n", + " 'the angular velocity based on the curvature of the global path.',\n", + " 'filename': 'nav2_core::GoalChecker',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_pure_pursuit_controller\\n'\n", + " '::\\n'\n", + " 'PurePursuitController\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'Controller\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::Controller',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'pursuit\\n'\n", + " 'controller\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'pure_pursuit_controller_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' controller_plugins: [\"FollowPath\"]\\n'\n", + " '\\n'\n", + " ' FollowPath:\\n'\n", + " ' plugin: \"nav2_pure_pursuit_controller::PurePursuitController\" '\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' debug_trajectory_details: True\\n'\n", + " ' desired_linear_vel: 0.2\\n'\n", + " ' lookahead_dist: 0.4\\n'\n", + " ' max_angular_vel: 1.0\\n'\n", + " ' transform_tolerance: 1.0\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a Smoother to a BT\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner.\n", + "Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2.\n", + "\n", + "## Requirements\n", + "You must install Nav2, Turtlebot3.\n", + "If you don’t have them installed, please followGetting Started.\n", + "You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing.\n", + "You should also have a copy of thenav2_params.yamlfile for your system to edit as well.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Familiarization with the Smoother BT Node\n", + "TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages.\n", + "Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API.\n", + "\n", + "## 1- Specifying a Smoother Plugin\n", + "In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use.\n", + "For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface.\n", + "Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot.\n", + "\n", + "## 2- Modifying your BT XML\n", + "Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking).\n", + "Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port.\n", + "A given behavior tree will have a line:\n", + "This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with:\n", + "If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree:\n", + "And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments.\n", + "If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path=\"{path}\"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path=\"{smoothed_path}\").\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"simple_smoother\"\\n'\n", + " ',\\n'\n", + " '\"curvature_smoother\"\\n'\n", + " ']\\n'\n", + " 'simple_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_smoother::SimpleSmoother\"\\n'\n", + " 'tolerance\\n'\n", + " ':\\n'\n", + " '1.0e-10\\n'\n", + " 'do_refinement\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'curvature_smoother\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_ceres_costaware_smoother/CeresCostawareSmoother\"',\n", + " 'context': 'Under each name, the parameters for that particular algorithm '\n", + " 'must be specified along with thepluginname for pluginlib to load '\n", + " 'a given algorithm’s library. An example configuration of 2 '\n", + " 'smoother plugins is shown below that could be used in '\n", + " 'thenav2_params.yamlfor your robot.',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'A given behavior tree will have a line:',\n", + " 'filename': 'smoother_id',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This line calls the planner server and return a path to '\n", + " 'thepathblackboard variable in the behavior tree. We are going '\n", + " 'to replace that line with the following to compute the path, '\n", + " 'smooth the path, and finally replace thepathblackboard variable '\n", + " 'with the new smoothed path that the system will now interact '\n", + " 'with:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'If you wish to have recoveries for the smoother error codes, '\n", + " 'such as triggering the system recoveries branch of a behavior '\n", + " 'tree:',\n", + " 'filename': 'path',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Publisher\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": DWB plugin name defined in thecontroller_plugin_idsparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Planner Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When theplanner_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"GridBased\"\\n'\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_navfn_planner::NavfnPlanner\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'expected_planner_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': '“nav2_navfn_planner::NavfnPlanner”',\n", + " 'filename': 'planner_plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Costmap2D Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own simplepluginfor Costmap2D.\n", + "Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Write a new Costmap2D plugin\n", + "For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap.\n", + "The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package.\n", + "Please refer to it when making your own layer plugin for Costmap2D.\n", + "The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer:\n", + "The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below:\n", + "In our example these methods have the following functionality:\n", + "and setsneed_recalculation_bounds recalculation indicator:\n", + "where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step:\n", + "These parameters are defined in plugin’s header file.\n", + "\n", + "## 2- Export and make GradientLayer plugin\n", + "The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it.\n", + "In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows:\n", + "This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top.\n", + "The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type:\n", + "Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file:\n", + "After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary.\n", + "Now the plugin is ready to use.\n", + "\n", + "## 3- Enable the plugin in Costmap2D\n", + "At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file.\n", + "For example:\n", + "YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name.\n", + "NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example:\n", + "In this case each plugin object will be handled by its own parameters tree in a YAML-file, like:\n", + "\n", + "## 4- Run GradientLayer plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient:\n", + "\n", + "Code Blocks:\n", + "[{'code': 'namespace\\n'\n", + " 'nav2_gradient_costmap_plugin\\n'\n", + " '{\\n'\n", + " 'class\\n'\n", + " 'GradientLayer\\n'\n", + " ':\\n'\n", + " 'public\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " '::\\n'\n", + " 'Layer',\n", + " 'context': 'The plugin classnav2_gradient_costmap_plugin::GradientLayeris '\n", + " 'inherited from basic classnav2_costmap_2d::Layer:',\n", + " 'filename': 'nav2_costmap_2d::Layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'declareParameter\\n'\n", + " '(\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'ParameterValue\\n'\n", + " '(\\n'\n", + " 'true\\n'\n", + " '));\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " 'name_\\n'\n", + " '+\\n'\n", + " '\".\"\\n'\n", + " '+\\n'\n", + " '\"enabled\"\\n'\n", + " ',\\n'\n", + " 'enabled_\\n'\n", + " ');',\n", + " 'context': 'GradientLayer::onInitialize()contains declaration of a ROS '\n", + " 'parameter with its default value:',\n", + " 'filename': 'GradientLayer::onInitialize()',\n", + " 'language': 'unknown'},\n", + " {'code': 'need_recalculation_\\n=\\nfalse\\n;',\n", + " 'context': 'and setsneed_recalculation_bounds recalculation indicator:',\n", + " 'filename': 'need_recalculation_',\n", + " 'language': 'unknown'},\n", + " {'code': 'int\\n'\n", + " 'gradient_index\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'j\\n'\n", + " '=\\n'\n", + " 'min_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '<\\n'\n", + " 'max_j\\n'\n", + " ';\\n'\n", + " 'j\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '// Reset gradient_index each time when reaching the end of '\n", + " 're-calculated window\\n'\n", + " '// by OY axis.\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'for\\n'\n", + " '(\\n'\n", + " 'int\\n'\n", + " 'i\\n'\n", + " '=\\n'\n", + " 'min_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '<\\n'\n", + " 'max_i\\n'\n", + " ';\\n'\n", + " 'i\\n'\n", + " '++\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'index\\n'\n", + " '=\\n'\n", + " 'master_grid\\n'\n", + " '.\\n'\n", + " 'getIndex\\n'\n", + " '(\\n'\n", + " 'i\\n'\n", + " ',\\n'\n", + " 'j\\n'\n", + " ');\\n'\n", + " '// setting the gradient cost\\n'\n", + " 'unsigned\\n'\n", + " 'char\\n'\n", + " 'cost\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'LETHAL_OBSTACLE\\n'\n", + " '-\\n'\n", + " 'gradient_index\\n'\n", + " '*\\n'\n", + " 'GRADIENT_FACTOR\\n'\n", + " ')\\n'\n", + " '%\\n'\n", + " '255\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'gradient_index\\n'\n", + " '<=\\n'\n", + " 'GRADIENT_SIZE\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '++\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'gradient_index\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'master_array\\n'\n", + " '[\\n'\n", + " 'index\\n'\n", + " ']\\n'\n", + " '=\\n'\n", + " 'cost\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'GradientLayer::updateCosts()- in this method the gradient is '\n", + " 'writing directly to the resulting costmapmaster_gridwithout '\n", + " 'merging with previous layers. This is equal to working with '\n", + " 'internalcostmap_and then callingupdateWithTrueOverwrite()method. '\n", + " 'Here is the gradient making algorithm for master costmap:',\n", + " 'filename': 'updateWithTrueOverwrite()',\n", + " 'language': 'unknown'},\n", + " {'code': '#include \"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, '\n", + " 'nav2_costmap_2d::Layer)\\n',\n", + " 'context': 'Plugin’s class should be registered with a basic type of loaded '\n", + " 'class. For this there is a special '\n", + " 'macroPLUGINLIB_EXPORT_CLASSshould be added to any source-file '\n", + " 'composing the plugin library:',\n", + " 'filename': 'PLUGINLIB_EXPORT_CLASS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'an\\n'\n", + " 'example\\n'\n", + " 'plugin\\n'\n", + " 'which\\n'\n", + " 'puts\\n'\n", + " 'repeating\\n'\n", + " 'costs\\n'\n", + " 'gradients\\n'\n", + " 'to\\n'\n", + " 'costmap\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Plugin description in a text form.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_costmap_2d '\n", + " 'gradient_layer.xml)\\n',\n", + " 'context': 'The export of plugin is performed by '\n", + " 'includingpluginlib_export_plugin_description_file()cmake-function '\n", + " 'intoCMakeLists.txt. This function installs plugin description '\n", + " 'file intosharedirectory and sets ament indexes for plugin '\n", + " 'description XML to be discoverable as a plugin of selected type:',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " ' \\n'\n", + " ' ...\\n'\n", + " '\\n',\n", + " 'context': 'Plugin description file is also should be added '\n", + " 'topackage.xml.costmap_2dis the package of the interface '\n", + " 'definition, for our caseLayer, and requires a path to the xml '\n", + " 'file:',\n", + " 'filename': 'Layer',\n", + " 'language': 'unknown'},\n", + " {'code': '--- a/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '+++ b/nav2_bringup/bringup/params/nav2_params.yaml\\n'\n", + " '@@ -124,8 +124,8 @@ local_costmap:\\n'\n", + " ' width: 3\\n'\n", + " '\\n'\n", + " ' height: 3\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " '- plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' inflation_layer:\\n'\n", + " '\\n'\n", + " ' cost_scaling_factor: 3.0\\n'\n", + " '\\n'\n", + " '@@ -171,8 +171,8 @@ global_costmap:\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " '\\n'\n", + " ' global_frame: map\\n'\n", + " '\\n'\n", + " ' use_sim_time: True\\n'\n", + " '\\n'\n", + " '- plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " '+ plugins: [\"static_layer\", \"obstacle_layer\", \"voxel_layer\", '\n", + " '\"gradient_layer\"]\\n'\n", + " ' robot_radius: 0.22\\n'\n", + " '\\n'\n", + " ' resolution: 0.05\\n'\n", + " '\\n'\n", + " ' obstacle_layer:\\n',\n", + " 'context': 'For example:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'plugins: [\"obstacle_layer\", \"gradient_layer_1\", '\n", + " '\"gradient_layer_2\"]\\n',\n", + " 'context': 'NOTE: there could be many simultaneously loaded plugin objects '\n", + " 'of one type. For this,plugin_nameslist should contain different '\n", + " 'plugins names whether theplugin_typeswill remain the same types. '\n", + " 'For example:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': 'gradient_layer_1:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: True\\n'\n", + " ' ...\\n'\n", + " 'gradient_layer_2:\\n'\n", + " ' plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and '\n", + " 'older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' enabled: False\\n'\n", + " ' ...\\n',\n", + " 'context': 'In this case each plugin object will be handled by its own '\n", + " 'parameters tree in a YAML-file, like:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\nros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions how to make it are written atGetting Started. Below '\n", + " 'is shortcut command for that:',\n", + " 'filename': 'plugin_types',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Waypoint Follower\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugin\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': '“nav2_waypoint_follower::WaitAtWaypoint”',\n", + " 'filename': 'nav2_waypoint_follower',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Loopback Simulator\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'loopback_simulator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'map_frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'scan_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_scan\"\\n'\n", + " \"# tb4_loopback_simulator.launch.py remaps to 'rplidar_link'\\n\"\n", + " 'update_duration\\n'\n", + " ':\\n'\n", + " '0.02',\n", + " 'context': 'Whether or not to publish simulated clock to/clock',\n", + " 'filename': '/clock',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: IsBatteryCharging\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Checks if the battery is charging by subscribing to '\n", + " 'asensor_msgs/BatteryStatetopic and checking if the '\n", + " 'power_supply_status isPOWER_SUPPLY_STATUS_CHARGING.\\n'\n", + " 'Returns SUCCESS in that case, FAILURE otherwise.',\n", + " 'filename': 'POWER_SUPPLY_STATUS_CHARGING',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Speed Limits\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map.\n", + "Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula:\n", + "where:\n", + "The decodedspeed_limitvalue may have one of two meanings:\n", + "The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages.\n", + "In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed.\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction:\n", + "Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot.\n", + "We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent.\n", + "After all speed restriction areas will be filled, save thespeed_mask.pgmimage.\n", + "Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0):\n", + "Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks.\n", + "In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Speed Filter\n", + "Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined:\n", + "Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage.\n", + "You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour.\n", + "In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration:\n", + "As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass.\n", + "Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started:\n", + "For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask.\n", + "Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'speed_limit\\n=\\nfilter_mask_data\\n*\\nmultiplier\\n+\\nbase\\n;',\n", + " 'context': 'Let’s look, how it is being decoded. As we '\n", + " 'know,OccupancyGridvalues are belonging to the[0..100]range. For '\n", + " 'Speed Filter0value means no speed limit in the area '\n", + " 'corresponding zero-cell on mask. Values from[1..100]range are '\n", + " 'being linearly converted into a speed limit value by the '\n", + " 'following formula:',\n", + " 'filename': '[1..100]',\n", + " 'language': 'unknown'},\n", + " {'code': 'image\\n'\n", + " ':\\n'\n", + " 'turtlebot3_world.pgm\\n'\n", + " '->\\n'\n", + " 'image\\n'\n", + " ':\\n'\n", + " 'speed_mask.pgm\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'trinary\\n'\n", + " '->\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " 'scale\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.196\\n'\n", + " '->\\n'\n", + " 'occupied_thresh\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'free_thresh\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'Like all other maps, the filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. '\n", + " 'Openspeed_mask.yamland update the fields as shown below (as '\n", + " 'mentioned before for thescalemode to use whole color lightness '\n", + " 'range there should be no '\n", + " 'thresholds:free_thresh=0.0andoccupied_thresh=1.0):',\n", + " 'filename': 'occupied_thresh=1.0',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " '# Create our own temporary YAML files that include substitutions\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'params'\\n\"\n", + " ',\\n'\n", + " \"'speed_params.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS 2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " ',\\n'\n", + " \"'maps'\\n\"\n", + " ',\\n'\n", + " \"'speed_mask.yaml'\\n\"\n", + " '),\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " '# Nodes launching commands\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " 'start_map_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '])\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_lifecycle_manager_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_map_server_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'start_costmap_filter_info_server_cmd\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Speed Filter in your configuration, both '\n", + " 'servers should be enabled as lifecycle nodes in Python '\n", + " 'launch-file. For example, this might look as follows, though '\n", + " 'adding them as Composition Nodes to your Navigation Component '\n", + " 'Container is also possible:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/speed_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"speed_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " 'src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Speed Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"speed_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' speed_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::SpeedFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'In this tutorial, we will enable Speed Filter for the global '\n", + " 'costmap. For this use the following configuration:',\n", + " 'filename': 'SpeedFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' speed_limit_topic: \"/speed_limit\"\\n',\n", + " 'context': 'Setspeed_limit_topicparameter of a Controller Server to the same '\n", + " 'value as it set forspeed_filterplugin:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Speed Filter was enabled for global/local costmap, '\n", + " 'run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'speed_filter',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: TransformAvailable\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Parent frame for transform.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigate To Pose\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'While this behavior tree does not make use of it, '\n", + " 'thePlannerSelector,ControllerSelector, '\n", + " 'andGoalCheckerSelectorbehavior tree nodes can also be helpful. '\n", + " 'Rather than hardcoding the algorithm to use '\n", + " '(GridBasedandFollowPath), these behavior tree nodes will allow a '\n", + " 'user to dynamically change the algorithm used in the navigation '\n", + " 'system via a ROS topic. It may be instead advisable to create '\n", + " 'different subtree contexts using condition nodes with specified '\n", + " 'algorithms in their most useful and unique situations. However, '\n", + " 'the selector nodes can be a useful way to change algorithms from '\n", + " 'an external application rather than via internal behavior tree '\n", + " 'control flow logic. It is better to implement changes through '\n", + " 'behavior tree methods, but we understand that many professional '\n", + " 'users have external applications to dynamically change settings '\n", + " 'of their navigators.',\n", + " 'filename': 'FollowPath',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Map Server / Saver\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Map Saver Parameters\n", + "\n", + "\n", + "## Map Server Parameters\n", + "\n", + "\n", + "## Costmap Filter Info Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'map_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"turtlebot3_world.yaml\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'map_saver\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'save_map_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'free_thresh_default\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'occupied_thresh_default\\n'\n", + " ':\\n'\n", + " '0.65\\n'\n", + " 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'filter_space_value=base+multiplier*mask_value',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: DWB Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Controller\n", + "\n", + "\n", + "## Plugins\n", + "The plugins listed below are inside thedwb_pluginsnamespace.\n", + "\n", + "## Trajectory Critics\n", + "The trajectory critics listed below are inside thedwb_criticsnamespace.\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# controller server parameters (see Controller Server for more '\n", + " 'info)\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# DWB controller parameters\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'debug_trajectory_details\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'min_vel_x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'min_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_x\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'max_vel_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_vel_theta\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_speed_xy\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_speed_xy\\n'\n", + " ':\\n'\n", + " '0.26\\n'\n", + " 'min_speed_theta\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_x\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'acc_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'acc_lim_theta\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'decel_lim_x\\n'\n", + " ':\\n'\n", + " '-2.5\\n'\n", + " 'decel_lim_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'decel_lim_theta\\n'\n", + " ':\\n'\n", + " '-3.2\\n'\n", + " 'vx_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'vy_samples\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'vtheta_samples\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'sim_time\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'linear_granularity\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'angular_granularity\\n'\n", + " ':\\n'\n", + " '0.025\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'trans_stopped_velocity\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'short_circuit_trajectory_evaluation\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'limit_vel_cmd_in_traj\\n'\n", + " ':\\n'\n", + " 'False\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"RotateToGoal\"\\n'\n", + " ',\\n'\n", + " '\"Oscillation\"\\n'\n", + " ',\\n'\n", + " '\"BaseObstacle\"\\n'\n", + " ',\\n'\n", + " '\"GoalAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathAlign\"\\n'\n", + " ',\\n'\n", + " '\"PathDist\"\\n'\n", + " ',\\n'\n", + " '\"GoalDist\"\\n'\n", + " ']\\n'\n", + " 'BaseObstacle.scale\\n'\n", + " ':\\n'\n", + " '0.02\\n'\n", + " 'PathAlign.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalAlign.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'PathAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'GoalAlign.forward_point_distance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'PathDist.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'GoalDist.scale\\n'\n", + " ':\\n'\n", + " '24.0\\n'\n", + " 'RotateToGoal.scale\\n'\n", + " ':\\n'\n", + " '32.0\\n'\n", + " 'RotateToGoal.slowing_factor\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'RotateToGoal.lookahead_time\\n'\n", + " ':\\n'\n", + " '-1.0',\n", + " 'context': 'The trajectory critics listed below are inside '\n", + " 'thedwb_criticsnamespace.',\n", + " 'filename': 'dwb_critics',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (SLAM) Navigating While Mapping\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains how to use Nav2 with SLAM.\n", + "The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around.\n", + "This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot.\n", + "Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2.\n", + "In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox\n", + "\n", + "## Requirements\n", + "You must install Navigation2, Turtlebot3, and SLAM Toolbox.\n", + "If you don’t have them installed, please followGetting Started.\n", + "SLAM Toolbox can be installed via:\n", + "or from built from source in your workspace with:\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Launch Robot Interfaces\n", + "For this tutorial, we will use the turtlebot3.\n", + "The turtlebot3 software can be installed via the following or on theturtlebot3 repository:\n", + "If you have another robot, replace with your robot specific interfaces.\n", + "Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like.\n", + "Run the following commands first whenever you open a new terminal during this tutorial.\n", + "Launch your robot’s interface and robot state publisher, for example:\n", + "\n", + "## 1- Launch Navigation2\n", + "Launch Navigation without nav2_amcl and nav2_map_server.\n", + "It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform.\n", + "\n", + "## 2- Launch SLAM\n", + "Bring up your choice of SLAM implementation.\n", + "Make sure it provides the map->odom transform and /map topic.\n", + "Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc.\n", + "For this tutorial, we will useSLAM Toolbox.\n", + "\n", + "## 3- Working with SLAM\n", + "Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie:\n", + "You should see the map update live! To save this map to file:\n", + "\n", + "## 4- Getting Started Simplification\n", + "If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration.\n", + "Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true.\n", + "We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--turtlebot3\\n'\n", + " 'ros--turtlebot3-msgs\\n'\n", + " 'ros--turtlebot3-bringup\\n',\n", + " 'context': 'For this tutorial, we will use the turtlebot3.\\n'\n", + " 'The turtlebot3 software can be installed via the following or on '\n", + " 'theturtlebot3 repository:',\n", + " 'filename': 'gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'topic\\n'\n", + " 'pub\\n'\n", + " '/goal_pose\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " '\"{header: {stamp: {sec: 0}, frame_id: \\'map\\'}, pose: {position: '\n", + " '{x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}\"',\n", + " 'context': 'Move your robot by requesting a goal through RViz or the ROS 2 '\n", + " 'CLI, ie:',\n", + " 'filename': 'ros2launchslam_toolboxonline_async_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'slam:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'If you’re only interested in running SLAM in the turtlebot3 '\n", + " 'getting started sandbox world, we also provide a simple way to '\n", + " 'enable SLAM as a launch configuration.\\n'\n", + " 'Rather than individually launching the interfaces, navigation, '\n", + " 'and SLAM, you can continue to use '\n", + " 'thetb3_simulation_launch.pywithslamconfig set to true.\\n'\n", + " 'We provide the instructions above with the assumption that you’d '\n", + " 'like to run SLAM on your own robot which would have separated '\n", + " 'simulation / robot interfaces and navigation launch files that '\n", + " 'are combined intb3_simulation_launch.pyfor the purposes of easy '\n", + " 'testing.',\n", + " 'filename': 'tb3_simulation_launch.py',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Using Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use.\n", + "Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package.\n", + "\n", + "## What is the Rotation Shim Controller?\n", + "This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers.\n", + "Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so.\n", + "Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task.\n", + "TheRotationShimControlleris most suitable for:\n", + "\n", + "## Configuring Rotation Shim Controller\n", + "This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through.\n", + "As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel.\n", + "The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted.\n", + "\n", + "## Configuring Primary Controller\n", + "There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity).\n", + "An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform.\n", + "\n", + "## Demo Execution\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'As such, its configuration looks very similar to that of any '\n", + " 'other plugin. In the code block below, you can see that we’ve '\n", + " 'added theRotationShimControlleras the plugin for path tracking '\n", + " 'in the controller server. You can see that we’ve also configured '\n", + " 'it below with its internal '\n", + " 'parameters,angular_dist_thresholdthroughmax_angular_accel.',\n", + " 'filename': 'max_angular_accel',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# DWB parameters\\n'\n", + " '...\\n'\n", + " '...\\n'\n", + " '...',\n", + " 'context': 'There is one more remaining parameter of '\n", + " 'theRotationShimControllernot mentioned above, '\n", + " 'theprimary_controller. This is the type of controller that your '\n", + " 'application would like to use as the primary modus operandi. It '\n", + " 'will share the same name and yaml namespace as the shim plugin. '\n", + " 'You can observe this below with the primary controller set '\n", + " 'theDWB(with the progress and goal checkers removed for brevity).',\n", + " 'filename': 'DWB',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dashing to Eloquent\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Packages\n", + "Navigation2 now includes a new packagenav2_waypoint_follower.\n", + "The waypoint follower is an action server that will take in a list of waypoints to follow and follow them in order.\n", + "There is a parameterstop_on_failurewhether the robot should continue to the next waypoint on a single waypoint failure,\n", + "or to return fail to the action client.\n", + "The waypoint follower is also a reference application for how to use the Navigation2 action server to complete a basic autonomy task.\n", + "Navigation2 now supports new algorithms for control and SLAM.\n", + "The Timed-Elastic Band (TEB) controller was implementedand can be found here.\n", + "It is its own controller plugin that can be used instead of the DWB controller.\n", + "Nav2 also supports SLAM Toolbox as the default SLAM implementation for ROS 2.\n", + "This replaces the use of Cartographer.\n", + "\n", + "## New Plugins\n", + "Eloquent introduces back in pluginlib plugins to the navigation stack.nav2_coredefines the plugin header interfaces to be used to implement controller, planner, recovery, and goal checker plugins.\n", + "All algorithms (NavFn, DWB, recoveries) were added as plugin interfaces and the general packages for servers were created.nav2_planneris the action server for planning that hosts a plugin for the planner.nav2_controlleris the action server for controller that hosts a plugin for the controller.nav2_recoveryis the action server for recovery that hosts a plugin for recovery.\n", + "New recovery plugins were added including backup, which will take in a distance to back up, if collision-free.\n", + "Additionally, the wait recovery was added that will wait a configurable period of time before trying to navigate again.\n", + "This plugin is especially helpful for time-dependent obstacles or pausing navigation for a scene to become less dynamic.\n", + "Many new behavior tree nodes were added. These behavior tree nodes are hard-coded in the behavior tree engine.\n", + "Behavior tree cpp v3 supports plugins and will be converted in the next release.\n", + "\n", + "## Navigation2 Architectural Changes\n", + "Thenav2_world_modelpackage was removed. The individualnav2_plannerandnav2_controllerservers now host their relevant costmaps.\n", + "This was done to reduce network traffic and ensure up-to-date information for the safety-critical elements of the system.\n", + "As above mentions, plugins were introduced into the stack and these servers each host plugins for navigation, control, and costmap layers.\n", + "Map server was substantially refactored but the external API remains the same. It now uses the SDL library for image loading.\n", + "TF-based positioning is now used for pose-estimation everywhere in the stack.\n", + "Prior, some elements of the navigation stack only updated its pose from the/amcl_posetopic publishing at an irregular rate.\n", + "This is obviously low-accuracy and high-latency.\n", + "All positioning is now based on the TF tree from the global frame to the robot frame.\n", + "Prior to Eloquent, there were no ROS 2 action servers and clients available.\n", + "Navigation2, rather, used an interface we called Tasks.\n", + "Eloquent now contains actions and a simple action server interface was created and is used now throughout the stack.\n", + "Tasks were removed.\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Configuration Guide\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: AMCL\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'amcl\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'alpha1\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha2\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha3\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha4\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'alpha5\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'base_frame_id\\n'\n", + " ':\\n'\n", + " '\"base_footprint\"\\n'\n", + " 'beam_skip_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'beam_skip_error_threshold\\n'\n", + " ':\\n'\n", + " '0.9\\n'\n", + " 'beam_skip_threshold\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'do_beamskip\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'global_frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'lambda_short\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'laser_likelihood_max_dist\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'laser_max_range\\n'\n", + " ':\\n'\n", + " '100.0\\n'\n", + " 'laser_min_range\\n'\n", + " ':\\n'\n", + " '-1.0\\n'\n", + " 'laser_model_type\\n'\n", + " ':\\n'\n", + " '\"likelihood_field\"\\n'\n", + " 'max_beams\\n'\n", + " ':\\n'\n", + " '60\\n'\n", + " 'max_particles\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'min_particles\\n'\n", + " ':\\n'\n", + " '500\\n'\n", + " 'odom_frame_id\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'pf_err\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'pf_z\\n'\n", + " ':\\n'\n", + " '0.99\\n'\n", + " 'recovery_alpha_fast\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'recovery_alpha_slow\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'resample_interval\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'robot_model_type\\n'\n", + " ':\\n'\n", + " '\"nav2_amcl::DifferentialMotionModel\"\\n'\n", + " 'save_pose_rate\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'sigma_hit\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'tf_broadcast\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'update_min_a\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'update_min_d\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'z_hit\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'z_max\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_rand\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'z_short\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'scan_topic\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'set_initial_pose\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'always_reset_initial_pose\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'first_map_only\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'initial_pose\\n'\n", + " ':\\n'\n", + " 'x\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0',\n", + " 'context': 'The lifecycle node bond mechanism publishing period (on the '\n", + " '/bond topic). Disabled if inferior or equal to 0.0.',\n", + " 'filename': 'first_map_only_',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Odometry\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Odometry Introduction\n", + "The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics.\n", + "Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe.\n", + "As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section.\n", + "In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information:\n", + "This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id.\n", + "\n", + "## Setting Up Odometry on your Robot\n", + "Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2.\n", + "To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below:\n", + "Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here\n", + "An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control.\n", + "For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system.\n", + "\n", + "## Simulating an Odometry System using Gazebo\n", + "In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here.\n", + "As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2.\n", + "\n", + "## Setup and Prerequisites\n", + "Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation.\n", + "We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo:\n", + "You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here.\n", + "Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS.\n", + "For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model.\n", + "Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF:\n", + "Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively.\n", + "To include this plugin in our URDF, add the following lines after thetag of the IMU plugin:\n", + "\n", + "## Launch and Build Files\n", + "We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description():\n", + "Remove the followingguiparam:\n", + "Remove the condition and parameters. Add arguments to thejoint_state_publisher_node:\n", + "Next, openpackage.xmland delete the line:\n", + "To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py\n", + "We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Then add the linespawn_entity,before therviz_nodeline, as shown below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system.\n", + "Navigate to the root of the project and execute the following lines:\n", + "Gazebo should launch and you should see a 3D model ofsam_bot:\n", + "To see the active topics in the system, open a new terminal and execute:\n", + "You should see/demo/imuand/demo/odomin the list of topics.\n", + "To see more information about the topics, execute:\n", + "You should see an output similar to below:\n", + "Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2.\n", + "\n", + "## Robot Localization Demo\n", + "Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages.\n", + "A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS.\n", + "Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic.\n", + "If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output.\n", + "For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics.\n", + "\n", + "## Configuring Robot Localization\n", + "Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform.\n", + "First, install therobot_localizationpackage using your machines package manager or by executing the following command:\n", + "Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile.\n", + "In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere.\n", + "To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu.\n", + "You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0.\n", + "In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs.\n", + "\n", + "## Launch and Build Files\n", + "Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line.\n", + "Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block.\n", + "Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node.\n", + "Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag.\n", + "Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "Let us now build and run our package. Navigate to the root of the project and execute the following lines:\n", + "Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot:\n", + "Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute:\n", + "You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics.\n", + "You can also check the subscriber count of these topics again by executing:\n", + "You should see that/demo/imuand/demo/odomnow both have 1 subscriber each.\n", + "To verify that theekf_filter_nodeare the subscribers of these topics, execute:\n", + "You should see an output as shown below.\n", + "From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics.\n", + "You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal:\n", + "You should see a continuous output similar to what is shown below.\n", + "\n", + "## Conclusion\n", + "In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization.\n", + "\n", + "Code Blocks:\n", + "[{'code': '# This represents estimates of position and velocity in free '\n", + " 'space.\\n'\n", + " '# The pose in this message should be specified in the coordinate '\n", + " 'frame given by header.frame_id\\n'\n", + " '# The twist in this message should be specified in the coordinate '\n", + " 'frame given by the child_frame_id\\n'\n", + " '# Includes the frame id of the pose parent.\\n'\n", + " '\\n'\n", + " 'std_msgs/Header\\n'\n", + " 'header\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Frame id the pose is pointing at. The twist is in this coordinate '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'child_frame_id\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated pose that is typically relative to a fixed world '\n", + " 'frame.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseWithCovariance\\n'\n", + " 'pose\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '# Estimated linear and angular velocity relative to '\n", + " 'child_frame_id.\\n'\n", + " '\\n'\n", + " 'geometry_msgs/TwistWithCovariance\\n'\n", + " 'twist\\n',\n", + " 'context': 'In addition to the requiredodom=>base_linktransform, Nav2 also '\n", + " 'requires the publishing ofnav_msgs/Odometrymessage because this '\n", + " 'message provides the velocity information of the robot. In '\n", + " 'detail, thenav_msgs/Odometrymessage contains the following '\n", + " 'information:',\n", + " 'filename': 'nav_msgs/Odometry',\n", + " 'language': 'unknown'},\n", + " {'code': 'linear\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '+\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " '2\\n'\n", + " 'angular\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'right_wheel_est_vel\\n'\n", + " '-\\n'\n", + " 'left_wheel_est_vel\\n'\n", + " ')\\n'\n", + " '/\\n'\n", + " 'wheel_separation\\n'\n", + " ';',\n", + " 'context': 'To start, we will use an example of a robot with wheel encoders '\n", + " 'as its odometry source. Note that wheel encoders are not '\n", + " 'required for Nav2 but it is common in most setups. The goal in '\n", + " 'setting up the odometry is to compute the odometry information '\n", + " 'and publish thenav_msgs/Odometrymessage '\n", + " 'andodom=>base_linktransform over ROS 2. To calculate this '\n", + " 'information, you will need to setup some code that will '\n", + " 'translate wheel encoder information into odometry information, '\n", + " 'similar to the snippet below:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--gazebo-ros-pkgs\\n',\n", + " 'context': 'We also need to install thegazebo_ros_pkgspackage to simulate '\n", + " 'odometry and control the robot with ROS 2 in Gazebo:',\n", + " 'filename': 'gazebo_ros_pkgs',\n", + " 'language': 'unknown'},\n", + " {'code': '132\\n'\n", + " '\\n'\n", + " '133\\n'\n", + " '\\n'\n", + " '134\\n'\n", + " '\\n'\n", + " '135\\n'\n", + " '\\n'\n", + " '136\\n'\n", + " '\\n'\n", + " '137\\n'\n", + " '\\n'\n", + " '138\\n'\n", + " '139\\n'\n", + " '\\n'\n", + " '140\\n'\n", + " '\\n'\n", + " '141\\n'\n", + " '\\n'\n", + " '142\\n'\n", + " '\\n'\n", + " '143\\n'\n", + " '\\n'\n", + " '144\\n'\n", + " '145\\n'\n", + " '\\n'\n", + " '146\\n'\n", + " '\\n'\n", + " '147\\n'\n", + " '148\\n'\n", + " '\\n'\n", + " '149\\n'\n", + " '\\n'\n", + " '150\\n'\n", + " '\\n'\n", + " '151\\n'\n", + " '\\n'\n", + " '152\\n'\n", + " '\\n'\n", + " '153\\n'\n", + " '154\\n'\n", + " '\\n'\n", + " '155\\n'\n", + " '\\n'\n", + " '156\\n'\n", + " '\\n'\n", + " '157\\n'\n", + " '\\n'\n", + " '158\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '159\\n'\n", + " '\\n'\n", + " '~/out:=imu\\n'\n", + " '\\n'\n", + " '160\\n'\n", + " '\\n'\n", + " '161\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '162\\n'\n", + " '\\n'\n", + " '163\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '164\\n'\n", + " '\\n'\n", + " '100\\n'\n", + " '\\n'\n", + " '165\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '166\\n'\n", + " '\\n'\n", + " '167\\n'\n", + " '\\n'\n", + " '168\\n'\n", + " '\\n'\n", + " '169\\n'\n", + " '\\n'\n", + " '170\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '171\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '172\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '173\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '174\\n'\n", + " '\\n'\n", + " '175\\n'\n", + " '\\n'\n", + " '176\\n'\n", + " '\\n'\n", + " '177\\n'\n", + " '\\n'\n", + " '178\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '179\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '181\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '182\\n'\n", + " '\\n'\n", + " '183\\n'\n", + " '\\n'\n", + " '184\\n'\n", + " '\\n'\n", + " '185\\n'\n", + " '\\n'\n", + " '186\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '187\\n'\n", + " '\\n'\n", + " '2e-4\\n'\n", + " '\\n'\n", + " '188\\n'\n", + " '\\n'\n", + " '0.0000075\\n'\n", + " '\\n'\n", + " '189\\n'\n", + " '\\n'\n", + " '0.0000008\\n'\n", + " '\\n'\n", + " '190\\n'\n", + " '\\n'\n", + " '191\\n'\n", + " '\\n'\n", + " '192\\n'\n", + " '\\n'\n", + " '193\\n'\n", + " '\\n'\n", + " '194\\n'\n", + " '\\n'\n", + " '195\\n'\n", + " '\\n'\n", + " '196\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '197\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '198\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '199\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '200\\n'\n", + " '\\n'\n", + " '201\\n'\n", + " '\\n'\n", + " '202\\n'\n", + " '\\n'\n", + " '203\\n'\n", + " '\\n'\n", + " '204\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '205\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '206\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '207\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '208\\n'\n", + " '\\n'\n", + " '209\\n'\n", + " '\\n'\n", + " '210\\n'\n", + " '\\n'\n", + " '211\\n'\n", + " '\\n'\n", + " '212\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '213\\n'\n", + " '\\n'\n", + " '1.7e-2\\n'\n", + " '\\n'\n", + " '214\\n'\n", + " '\\n'\n", + " '0.1\\n'\n", + " '\\n'\n", + " '215\\n'\n", + " '\\n'\n", + " '0.001\\n'\n", + " '\\n'\n", + " '216\\n'\n", + " '\\n'\n", + " '217\\n'\n", + " '\\n'\n", + " '218\\n'\n", + " '\\n'\n", + " '219\\n'\n", + " '\\n'\n", + " '220\\n'\n", + " '\\n'\n", + " '221\\n'\n", + " '',\n", + " 'context': 'Now, we will set up our IMU sensor plugin according to the '\n", + " 'description above by adding the following lines before '\n", + " 'theline in our URDF:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '223\\n'\n", + " '\\n'\n", + " '224\\n'\n", + " '\\n'\n", + " '225\\n'\n", + " '\\n'\n", + " '226\\n'\n", + " '\\n'\n", + " '/demo\\n'\n", + " '\\n'\n", + " '227\\n'\n", + " '\\n'\n", + " '228\\n'\n", + " '229\\n'\n", + " '\\n'\n", + " '230\\n'\n", + " '\\n'\n", + " 'drivewhl_l_joint\\n'\n", + " '\\n'\n", + " '231\\n'\n", + " '\\n'\n", + " 'drivewhl_r_joint\\n'\n", + " '\\n'\n", + " '232\\n'\n", + " '233\\n'\n", + " '\\n'\n", + " '234\\n'\n", + " '\\n'\n", + " '0.4\\n'\n", + " '\\n'\n", + " '235\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '236\\n'\n", + " '237\\n'\n", + " '\\n'\n", + " '238\\n'\n", + " '\\n'\n", + " '20\\n'\n", + " '\\n'\n", + " '239\\n'\n", + " '\\n'\n", + " '1.0\\n'\n", + " '\\n'\n", + " '240\\n'\n", + " '241\\n'\n", + " '\\n'\n", + " '242\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '243\\n'\n", + " '\\n'\n", + " 'false\\n'\n", + " '\\n'\n", + " '244\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '245\\n'\n", + " '246\\n'\n", + " '\\n'\n", + " 'odom\\n'\n", + " '\\n'\n", + " '247\\n'\n", + " '\\n'\n", + " 'base_link\\n'\n", + " '\\n'\n", + " '248\\n'\n", + " '\\n'\n", + " '249\\n'\n", + " '',\n", + " 'context': 'To include this plugin in our URDF, add the following lines '\n", + " 'after thetag of the IMU plugin:',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher_gui'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.IfCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " ')',\n", + " 'context': 'We will now edit our launch file,launch/display.launch.py, to '\n", + " 'spawnsam_botin Gazebo. Since we will be simulating our robot, we '\n", + " 'can remove the GUI for the joint state publisher by deleting the '\n", + " 'following lines inside thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'gui'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable joint_state_publisher_gui'\\n\"\n", + " ')',\n", + " 'context': 'Remove the followingguiparam:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'joint_state_publisher'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " 'default_model_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " '#Add this line\\n'\n", + " 'parameters\\n'\n", + " '=[{\\n'\n", + " \"'robot_description'\\n\"\n", + " ':\\n'\n", + " 'Command\\n'\n", + " '([\\n'\n", + " \"'xarcro '\\n\"\n", + " ',\\n'\n", + " 'default_model_path\\n'\n", + " '])}]\\n'\n", + " ',\\n'\n", + " '#Remove this line\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'launch.conditions.UnlessCondition\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'gui'\\n\"\n", + " '))\\n'\n", + " '# Remove this line\\n'\n", + " ')',\n", + " 'context': 'Remove the condition and parameters. Add arguments to '\n", + " 'thejoint_state_publisher_node:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'joint_state_publisher_gui\\n',\n", + " 'context': 'Next, openpackage.xmland delete the line:',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'To launch Gazebo, add the following before '\n", + " 'thejoint_state_publisher_node,line indisplay.launch.py',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'spawn_entity\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'gazebo_ros'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'spawn_entity.py'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'arguments\\n'\n", + " '=[\\n'\n", + " \"'-entity'\\n\"\n", + " ',\\n'\n", + " \"'sam_bot'\\n\"\n", + " ',\\n'\n", + " \"'-topic'\\n\"\n", + " ',\\n'\n", + " \"'robot_description'\\n\"\n", + " ']\\n'\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'We will now add a node that spawnssam_botin Gazebo. '\n", + " 'Openlaunch/display.launch.pyagain and paste the following lines '\n", + " 'before thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n\\nspawn_entity,\\n\\nrviz_node\\n\\n])',\n", + " 'context': 'Then add the linespawn_entity,before therviz_nodeline, as shown '\n", + " 'below.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Navigate to the root of the project and execute the following '\n", + " 'lines:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'To see the active topics in the system, open a new terminal and '\n", + " 'execute:',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'To see more information about the topics, execute:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'Type:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " 'Publisher\\n'\n", + " 'count:\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " 'Subscription\\n'\n", + " 'count:\\n'\n", + " '0',\n", + " 'context': 'You should see an output similar to below:',\n", + " 'filename': '/demo/odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--robot-localization\\n',\n", + " 'context': 'First, install therobot_localizationpackage using your machines '\n", + " 'package manager or by executing the following command:',\n", + " 'filename': 'robot_localization',\n", + " 'language': 'unknown'},\n", + " {'code': '### ekf config file ###\\n'\n", + " 'ekf_filter_node\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# The frequency, in Hz, at which the filter will output a position '\n", + " 'estimate. Note that the filter will not begin\\n'\n", + " '# computation until it receives at least one message from one of '\n", + " 'theinputs. It will then run continuously at the\\n'\n", + " '# frequency specified here, regardless of whether it receives more '\n", + " 'measurements. Defaults to 30 if unspecified.\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# ekf_localization_node and ukf_localization_node both use a 3D '\n", + " 'omnidirectional motion model. If this parameter is\\n'\n", + " '# set to true, no 3D information will be used in your state '\n", + " 'estimate. Use this if you are operating in a planar\\n'\n", + " '# environment and want to ignore the effect of small variations in '\n", + " 'the ground plane that might otherwise be detected\\n'\n", + " '# by, for example, an IMU. Defaults to false if unspecified.\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# Whether to publish the acceleration state. Defaults to false if '\n", + " 'unspecified.\\n'\n", + " 'publish_acceleration\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# Whether to broadcast the transformation over the /tf topic. '\n", + " 'Defaultsto true if unspecified.\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# 1. Set the map_frame, odom_frame, and base_link frames to the '\n", + " 'appropriate frame names for your system.\\n'\n", + " '# 1a. If your system does not have a map_frame, just remove it, '\n", + " 'and make sure \"world_frame\" is set to the value of odom_frame.\\n'\n", + " '# 2. If you are fusing continuous position data such as wheel '\n", + " 'encoder odometry, visual odometry, or IMU data, set \"world_frame\"\\n'\n", + " '# to your odom_frame value. This is the default behavior for '\n", + " \"robot_localization's state estimation nodes.\\n\"\n", + " '# 3. If you are fusing global absolute position data that is '\n", + " 'subject to discrete jumps (e.g., GPS or position updates from '\n", + " 'landmark\\n'\n", + " '# observations) then:\\n'\n", + " '# 3a. Set your \"world_frame\" to your map_frame value\\n'\n", + " '# 3b. MAKE SURE something else is generating the '\n", + " 'odom->base_link transform. Note that this can even be another state '\n", + " 'estimation node\\n'\n", + " '# from robot_localization! However, that instance should '\n", + " '*not* fuse the global data.\\n'\n", + " 'map_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " '# Defaults to \"map\" if unspecified\\n'\n", + " 'odom_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to \"odom\" if unspecified\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '# Defaults to \"base_link\" ifunspecified\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '# Defaults to the value ofodom_frame if unspecified\\n'\n", + " 'odom0\\n'\n", + " ':\\n'\n", + " 'demo/odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'demo/imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Next, we specify the parameters of theekf_nodeusing a YAML file. '\n", + " 'Create a directory namedconfigat the root of your project and '\n", + " 'create a file namedekf.yaml. Copy the following lines of code '\n", + " 'into yourekf.yamlfile.',\n", + " 'filename': 'ekf.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization_node\\n'\n", + " '=\\n'\n", + " 'launch_ros.actions.Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'robot_localization'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'ekf_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'ekf_filter_node'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'parameters\\n'\n", + " '=[\\n'\n", + " 'os.path.join\\n'\n", + " '(\\n'\n", + " 'pkg_share,\\n'\n", + " \"'config/ekf.yaml'\\n\"\n", + " ')\\n'\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')}]\\n'\n", + " ')',\n", + " 'context': 'Now, let us add theekf_nodeinto the launch file. '\n", + " 'Openlaunch/display.launch.pyand paste the following lines before '\n", + " 'thereturnlaunch.LaunchDescription([line.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " '\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Flag to enable use_sim_time'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Next, add the following launch arguments within '\n", + " 'thereturnlaunch.LaunchDescription([block.',\n", + " 'filename': 'returnlaunch.LaunchDescription([',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_state_publisher_node,\\n'\n", + " '\\n'\n", + " 'spawn_entity,\\n'\n", + " '\\n'\n", + " 'robot_localization_node,\\n'\n", + " '\\n'\n", + " 'rviz_node\\n'\n", + " '\\n'\n", + " '])',\n", + " 'context': 'Lastly, addrobot_localization_node,above therviz_nodeline to '\n", + " 'launch the robot localization node.',\n", + " 'filename': 'rviz_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'robot_localization\\n',\n", + " 'context': 'Next, we need to add therobot_localizationdependency to our '\n", + " 'package definition. Openpackage.xmland add the following line '\n", + " 'below the lasttag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'Lastly, openCMakeLists.txtand append theconfigdirectory inside '\n", + " 'theinstall(DIRECTORY...), as shown in the snippet below.',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now build and run our package. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'install(DIRECTORY...)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\nlist\\n',\n", + " 'context': 'Next, let us verify that theodometry/filtered,accel/filtered, '\n", + " 'and/tftopics are active in the system. Open a new terminal and '\n", + " 'execute:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\ntopic\\ninfo\\n/demo/imu\\nros2\\ntopic\\ninfo\\n/demo/odom\\n',\n", + " 'context': 'You can also check the subscriber count of these topics again by '\n", + " 'executing:',\n", + " 'filename': '/tf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nnode\\ninfo\\n/ekf_filter_node\\n',\n", + " 'context': 'To verify that theekf_filter_nodeare the subscribers of these '\n", + " 'topics, execute:',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': '/ekf_filter_node\\n'\n", + " 'Subscribers:\\n'\n", + " '\\n'\n", + " '/demo/imu:\\n'\n", + " 'sensor_msgs/msg/Imu\\n'\n", + " '\\n'\n", + " '/demo/odom:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/set_pose:\\n'\n", + " 'geometry_msgs/msg/PoseWithCovarianceStamped\\n'\n", + " 'Publishers:\\n'\n", + " '\\n'\n", + " '/accel/filtered:\\n'\n", + " 'geometry_msgs/msg/AccelWithCovarianceStamped\\n'\n", + " '\\n'\n", + " '/diagnostics:\\n'\n", + " 'diagnostic_msgs/msg/DiagnosticArray\\n'\n", + " '\\n'\n", + " '/odometry/filtered:\\n'\n", + " 'nav_msgs/msg/Odometry\\n'\n", + " '\\n'\n", + " '/parameter_events:\\n'\n", + " 'rcl_interfaces/msg/ParameterEvent\\n'\n", + " '\\n'\n", + " '/rosout:\\n'\n", + " 'rcl_interfaces/msg/Log\\n'\n", + " '\\n'\n", + " '/tf:\\n'\n", + " 'tf2_msgs/msg/TFMessage\\n'\n", + " 'Service\\n'\n", + " 'Servers:\\n'\n", + " '\\n'\n", + " '...\\n',\n", + " 'context': 'You should see an output as shown below.',\n", + " 'filename': 'ekf_filter_node',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nodom\\nbase_link\\n',\n", + " 'context': 'You may also verify thatrobot_localizationis publishing '\n", + " 'theodom=>base_linktransform by using the tf2_echo utility. Run '\n", + " 'the following command in a separate command line terminal:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '8\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " 'At\\n'\n", + " 'time\\n'\n", + " '9\\n'\n", + " '.842000000\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.002,\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.127\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '-0.000,\\n'\n", + " '0\\n'\n", + " '.092,\\n'\n", + " '0\\n'\n", + " '.003,\\n'\n", + " '0\\n'\n", + " '.996\\n'\n", + " ']',\n", + " 'context': 'You should see a continuous output similar to what is shown '\n", + " 'below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Waypoint Follower\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Provided Plugins\n", + "\n", + "\n", + "## Default Plugin\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': '“nav2_waypoint_follower::WaitAtWaypoint”',\n", + " 'filename': 'nav2_waypoint_follower',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Adding a New Nav2 Task Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Lifecycle Nodes\n", + "The Lifecycle node is the first key component of a nav2 task server. Lifecycle nodes were introduced in ROS 2 to systematically manage the bringup and shutdown of the different nodes involved in the robot’s operation. The use of Lifecycle nodes ensures that all nodes are successfully instantiated before they begin their execution and Nav2 shuts down all nodes if there is any unresponsive node.\n", + "Lifecycle nodes contain state machine transitions that enable deterministic behavior in ROS 2 servers. The Lifecycle node transitions in Nav2 are handled by theLifecycleManager. The Lifecycle Manager transitions the states of the Lifecycle nodes and provides greater control over the state of a system.\n", + "The primary states of a Lifecycle node areUnconfigured,Inactive,Active, andFinalized. A Lifecycle node starts in anUnconfiguredstate after being instantiated. The Lifecycle Manager transitions a node fromUnconfiguredtoInactiveby implementing theConfiguratingtransition. TheConfiguratingtransition sets up all configuration parameters and prepares any required setup such as memory allocation and the set up of the static publication and subscription topics. A node in theInactivestate is allowed to reconfigure its parameters and but cannot perform any processing. From theInactivestate, the Lifecycle Manager implements theActivatingtransition state to transition the node fromInactivetoActive, which is the main state. A node in theActivestate is allowed to perform any processing operation. In case a node crashes, the Lifecycle Manager shuts down the system to prevent any critical failures. On shutdown, the necessary cleanup operations are performed and the nodes are transitioned to theFinalizedstate viaDeactivating,CleaningUp, andShuttingDowntransition states.\n", + "You may wish to integrate your own nodes into the Nav2 framework or add new lifecycle nodes to your system. As an example, we will add a new notional lifecycle nodesensor_driver, and have it be controlled via the Nav2 Lifecycle Manager to ensure sensor feeds are available before activating navigation. You can do so by adding asensor_drivernode in your launch file and adding it to the list of nodes to be activated by thelifecycle_managerbefore navigation, as shown in the example below.\n", + "In the snippet above, the nodes to be handled by the Lifecycle Manager are set using thenode_namesparameter. Thenode_namesparameter takes in an ordered list of nodes to bringup through the Lifecycle transition. As shown in the snippet, thenode_namesparameter takes inlifecycle_nodeswhich contains the list of nodes to be added to the Lifecycle Manager. The Lifecycle Manager implements bringup transitions (ConfiguringandActivating) to the nodes one-by-one and in order, while the nodes are processed in reverse order for shutdown transitions. Hence, thesensor_driveris listed first before the other navigation servers so that the sensor data is available before the navigation servers are activated.\n", + "Two other parameters of the Lifecycle Manager areautostartandbond_timeout. Setautostarttotrueif you want to set the transition nodes to theActivestate on startup. Otherwise, you will need to manually trigger Lifecycle Manager to transition up the system. Thebond_timeoutsets the waiting time to decide when to transition down all of the nodes if a node is not responding.\n", + "\n", + "## Composition\n", + "Composition is the second key component nav2 task servers that was introduced to reduce the memory and CPU resources by putting multiple nodes in a single process. In Nav2, Composition can be used to compose all Nav2 nodes in a single process instead of launching them separately. This is useful for deployment on embedded systems where developers need to optimize resource usage.\n", + "In the following section, we give an example on how to add a new Nav2 server, which we notionally call theroute_server, to our system.\n", + "We make use of the launch files to compose different servers into a single process. The process is established by theComposableNodeContainercontainer that is populated with composition nodes viaComposableNode. This container can then be launched and used the same as any other Nav2 node.\n", + "\n", + "## Error codes\n", + "Your nav2 task server may also wish to return a ‘error_code’ in its action response (though not required). If there are semantically meaningful and actionable types of failures for your system, this is a systemic way to communicate those failures which may be automatically aggregated into the responses of the navigation system to your application.\n", + "It is important to note that error codes from 0-9999 are reserved for internal nav2 servers with each server offset by 100 while external servers start at 10000 and end at 65535.\n", + "The table below shows the current servers along with the expected error code structure.\n", + "Error codes are attached to the response of the action message. An example can be seen below for the route server. Note that by convention we set the error code field within the message definition toerror_code.\n", + "As stated in the message, the priority order of the errors should match the message order, 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "Since the the route server is a external server, the errors codes start at 10000 and go up to 10099.\n", + "In order to propagate your server’s error code to the rest of the system it must be added to the nav2_params.yaml file.\n", + "Theerror_code_id_namesinside of the BT Navigator define what error codes to look for on the blackboard by the server. The lowest error code of the sequence is then returned - whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "\n", + "## Conclusion\n", + "In this section of the guide, we have discussed Lifecycle Nodes, Composition and Error Codes which are new and important concepts in ROS 2. We also showed how to implement Lifecycle Nodes, Composition and Error Codes to your newly created nodes/servers with Nav2. These three concepts are helpful to efficiently run your system and therefore are encouraged to be used throughout Nav2.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'smoother_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " '...\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'sensor_driver'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " '],\\n'\n", + " 'remappings\\n'\n", + " '=\\n'\n", + " 'remappings\\n'\n", + " '),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_navigation'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),',\n", + " 'context': 'You may wish to integrate your own nodes into the Nav2 framework '\n", + " 'or add new lifecycle nodes to your system. As an example, we '\n", + " 'will add a new notional lifecycle nodesensor_driver, and have it '\n", + " 'be controlled via the Nav2 Lifecycle Manager to ensure sensor '\n", + " 'feeds are available before activating navigation. You can do so '\n", + " 'by adding asensor_drivernode in your launch file and adding it '\n", + " 'to the list of nodes to be activated by '\n", + " 'thelifecycle_managerbefore navigation, as shown in the example '\n", + " 'below.',\n", + " 'filename': 'lifecycle_manager',\n", + " 'language': 'unknown'},\n", + " {'code': 'container\\n'\n", + " '=\\n'\n", + " 'ComposableNodeContainer\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'my_container'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'rclcpp_components'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'component_container'\\n\"\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server::RouteServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'nav2_route_server'\\n\"\n", + " '),\\n'\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " ')',\n", + " 'context': 'Add a newComposableNode()instance in your launch file pointing '\n", + " 'to the component container of your choice.',\n", + " 'filename': 'ComposableNode()',\n", + " 'language': 'unknown'},\n", + " {'code': '\\nnav2_route_server\\n',\n", + " 'context': 'Add the package containing the server to yourpackage.xmlfile.',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': '# Error codes\\n'\n", + " '# Note: The expected priority order of the errors should match the '\n", + " 'message order\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'NONE\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " '# 0 is reserved for NONE\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'UNKNOWN\\n'\n", + " '=\\n'\n", + " '10000\\n'\n", + " '# first error code in the sequence is reserved for UNKNOWN\\n'\n", + " '# User Error codes below\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'INVALID_START\\n'\n", + " '=\\n'\n", + " '10001\\n'\n", + " '\\n'\n", + " 'int16\\n'\n", + " 'NO_VALID_ROUTE\\n'\n", + " '=\\n'\n", + " '10002\\n'\n", + " '#goal definition\\n'\n", + " '\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'goal\\n'\n", + " 'route_msgs/PoseStamped\\n'\n", + " 'start\\n'\n", + " 'string\\n'\n", + " 'route_id\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'nav_msgs/Route\\n'\n", + " 'route\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'route_time\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '---\\n',\n", + " 'context': 'Error codes are attached to the response of the action message. '\n", + " 'An example can be seen below for the route server. Note that by '\n", + " 'convention we set the error code field within the message '\n", + " 'definition toerror_code.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'error_code_id_names\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'compute_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'follow_path_error_code_id\\n'\n", + " '-\\n'\n", + " 'route_error_code_id',\n", + " 'context': 'In order to propagate your server’s error code to the rest of '\n", + " 'the system it must be added to the nav2_params.yaml file.\\n'\n", + " 'Theerror_code_id_namesinside of the BT Navigator define what '\n", + " 'error codes to look for on the blackboard by the server. The '\n", + " 'lowest error code of the sequence is then returned - whereas the '\n", + " 'code enums increase the higher up in the software stack - giving '\n", + " 'higher priority to lower-level failures.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: PipelineSequence\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Ticks the first child till it succeeds, then ticks the first and '\n", + " 'second children till the second one succeeds.\\n'\n", + " 'It then ticks the first, second, and third children until the '\n", + " 'third succeeds, and so on, and so on. If at any\\n'\n", + " 'time a child returns RUNNING, that doesn’t change the behavior. '\n", + " 'If at any time a child returns FAILURE, that\\n'\n", + " 'stops all children and returns FAILURE overall.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Inflation Layer Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Costmap 2D\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Costmap2D ROS Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thepluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Plugin Parameters\n", + "\n", + "\n", + "## Costmap Filters Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'filters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"keepout_filter\"\\n'\n", + " ',\\n'\n", + " '\"speed_filter\"\\n'\n", + " ']\\n'\n", + " 'keepout_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " 'speed_filter\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::SpeedFilter\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'footprint_padding\\n'\n", + " ':\\n'\n", + " '0.03\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '# radius set and used, so no footprint points\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'footprint_clearing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " '# no frame set, uses frame from message\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"PointCloud2\"\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'subscribe_to_updates\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'inflate_unknown\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'inflate_around_unknown\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': '“nav2_costmap_2d::InflationLayer”',\n", + " 'filename': 'plugins',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Lifecycle Manager\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'lifecycle_manager\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'node_names\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'controller_server'\\n\"\n", + " ',\\n'\n", + " \"'planner_server'\\n\"\n", + " ',\\n'\n", + " \"'behavior_server'\\n\"\n", + " ',\\n'\n", + " \"'bt_navigator'\\n\"\n", + " ',\\n'\n", + " \"'waypoint_follower'\\n\"\n", + " ']\\n'\n", + " 'bond_timeout\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'attempt_respawn_reconnection\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'bond_respawn_max_duration\\n'\n", + " ':\\n'\n", + " '10.0',\n", + " 'context': 'When a server crashes or becomes non-responsive, the lifecycle '\n", + " 'manager will bring down all nodes for safety. This is the '\n", + " 'duration of which the lifecycle manager will attempt to '\n", + " 'reconnect with the failed server(s) during to recover and '\n", + " 're-activate the system. If this passes, it will stop attempts '\n", + " 'and will require a manual re-activation once the problem is '\n", + " 'manually resolved. Units: seconds.',\n", + " 'filename': 'true',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Dev Containers\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## What, Why, How?\n", + "Lets briefly explain what dev containers are, why you should use them, and how they work.\n", + "\n", + "## What is a Dev Container?\n", + "A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system.\n", + "\n", + "## Why use a Dev Container?\n", + "A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS.\n", + "\n", + "## How do Dev Containers work?\n", + "When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more.\n", + "This is quite similar to earlier tools used to customize and run docker containers for development:\n", + "\n", + "## Prerequisites\n", + "To use dev containers, you’ll need the following:\n", + "\n", + "## Getting started\n", + "Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing.\n", + "While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment.\n", + "\n", + "## Security\n", + "A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent.\n", + "\n", + "=== Document ===\n", + "Title: Using Rotation Shim Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use.\n", + "Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package.\n", + "\n", + "## What is the Rotation Shim Controller?\n", + "This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers.\n", + "Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so.\n", + "Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task.\n", + "TheRotationShimControlleris most suitable for:\n", + "\n", + "## Configuring Rotation Shim Controller\n", + "This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through.\n", + "As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel.\n", + "The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted.\n", + "\n", + "## Configuring Primary Controller\n", + "There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity).\n", + "An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform.\n", + "\n", + "## Demo Execution\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0',\n", + " 'context': 'As such, its configuration looks very similar to that of any '\n", + " 'other plugin. In the code block below, you can see that we’ve '\n", + " 'added theRotationShimControlleras the plugin for path tracking '\n", + " 'in the controller server. You can see that we’ve also configured '\n", + " 'it below with its internal '\n", + " 'parameters,angular_dist_thresholdthroughmax_angular_accel.',\n", + " 'filename': 'max_angular_accel',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_rotation_shim_controller::RotationShimController\"\\n'\n", + " 'primary_controller\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"\\n'\n", + " 'angular_dist_threshold\\n'\n", + " ':\\n'\n", + " '0.785\\n'\n", + " 'forward_sampling_distance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'rotate_to_heading_angular_vel\\n'\n", + " ':\\n'\n", + " '1.8\\n'\n", + " 'max_angular_accel\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# DWB parameters\\n'\n", + " '...\\n'\n", + " '...\\n'\n", + " '...',\n", + " 'context': 'There is one more remaining parameter of '\n", + " 'theRotationShimControllernot mentioned above, '\n", + " 'theprimary_controller. This is the type of controller that your '\n", + " 'application would like to use as the primary modus operandi. It '\n", + " 'will share the same name and yaml namespace as the shim plugin. '\n", + " 'You can observe this below with the primary controller set '\n", + " 'theDWB(with the progress and goal checkers removed for brevity).',\n", + " 'filename': 'DWB',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Introduction To Nav2 Specific Nodes\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Action Nodes\n", + "Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list,\n", + "theClearCostmapServiceaction node isnotan action server client, but a service client.\n", + "\n", + "## Condition Nodes\n", + "The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise.\n", + "The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”.\n", + "Condition nodes are typically paired with ReactiveFallback nodes.\n", + "\n", + "## Decorator Nodes\n", + "\n", + "\n", + "## Control: PipelineSequence\n", + "ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING.\n", + "This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe).\n", + "If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS.\n", + "To explain this further, here is an example BT that uses PipelineSequence.\n", + "Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well.\n", + "For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide.\n", + "\n", + "## Control: Recovery\n", + "The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS.\n", + "If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either:\n", + "This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior,\n", + "and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed.\n", + "In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS.\n", + "Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete.\n", + "For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide.\n", + "\n", + "## Control: RoundRobin\n", + "The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS.\n", + "If all children returnFAILUREso will the parent RoundRobin.\n", + "Here is an example BT we will use to walk through the concept.\n", + "2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING.\n", + "In this case, no other children are ticked and the parent node returnsRUNNINGas well.\n", + "3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE.\n", + "This means thatAction_Bwill get ticked next, andAction_Cremains unticked.\n", + "Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING.\n", + "4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS.\n", + "The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did.\n", + "For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To explain this further, here is an example BT that uses '\n", + " 'PipelineSequence.',\n", + " 'filename': 'SUCCESS',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'This node is usually used to link together an action, and a '\n", + " 'recovery action as the name suggests. The first action will '\n", + " 'typically be the “main” behavior,\\n'\n", + " 'and the second action will be something to be done in case '\n", + " 'ofFAILUREof the main behavior. Often, the ticking of the second '\n", + " 'child action will promote the chance the first action will '\n", + " 'succeed.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Here is an example BT we will use to walk through the concept.',\n", + " 'filename': 'FAILURE',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Filtering of Noise-Induced Obstacles\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map.\n", + "This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Enable Denoise Layer\n", + "Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined:\n", + "Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage.\n", + "It is important to note thatDenoiseLayertypically should be placed before the inflation layer.\n", + "This is required to prevent inflation from noise-induced obstacles.\n", + "Moreover,DenoiseLayerprocesses only obstacle information in the costmap.\n", + "ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map).\n", + "If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing.\n", + "To enableDenoiseLayerfor both global and local costmaps, use the following configuration:\n", + "\n", + "## 2. Run Nav2 stack\n", + "After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly: with the default parameters,\n", + "no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial).\n", + "\n", + "## How it works\n", + "The plugin is based on two algorithms.\n", + "When parameterminimal_group_size= 2, the first algorithm turns on.\n", + "It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap.\n", + "White color of the kernel pixel means to use the value, black means to ignore it.\n", + "As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask.\n", + "In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case.\n", + "After that, obstacles corresponding to free space code on neighbors image are removed.\n", + "This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4.\n", + "Obstacles marked at the end of the animation will be removed.\n", + "When parameterminimal_group_size> 2, the second algorithm is executed.\n", + "This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size.\n", + "To select groups of adjacent obstacles, the algorithm performs their segmentation.\n", + "The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type.\n", + "Next, the size of each segment is calculated.\n", + "Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells.\n", + "This algorithm is about 10 times slower than first, so use it with caution and only when necessary.\n", + "Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size).\n", + "This algorithm is illustrated in the animation below (group_connectivity_type= 8).\n", + "Obstacles marked at the end of the animation will be removed (groups that size less 3).\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", \"denoise_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' denoise_layer:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"denoise_layer\", inflation_layer\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::DenoiseLayer\"\\n'\n", + " ' enabled: True\\n',\n", + " 'context': 'To enableDenoiseLayerfor both global and local costmaps, use the '\n", + " 'following configuration:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'headless:\\n'\n", + " '=\\n'\n", + " 'False\\n',\n", + " 'context': 'After Denoise Layer was enabled for global/local costmaps, run '\n", + " 'Nav2 stack as written inGetting Started:',\n", + " 'filename': 'DenoiseLayer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Navigator Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class.\n", + "In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system.\n", + "It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Create a new Navigator Plugin\n", + "We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin.\n", + "Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request.\n", + "Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs).\n", + "The list of methods, their descriptions, and necessity are presented in the table below:\n", + "In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed.\n", + "The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator.\n", + "In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage:\n", + "When a goal is received, we need to determine if this goal is valid and should be processed.\n", + "ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request.\n", + "Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided.\n", + "If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority.\n", + "Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below:\n", + "The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set).\n", + "The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in.\n", + "\n", + "## 2- Exporting the navigator plugin\n", + "Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server.\n", + "Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading\n", + "plugins is handled bypluginlib.\n", + "Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described.\n", + "Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting.\n", + "It is good practice to place these lines at the end of the file, but technically, you can also write at the top.\n", + "\n", + "## 3- Pass the plugin name through the params file\n", + "To enable the plugin, we need to modify thenav2_params.yamlfile as below\n", + "In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose.\n", + "To pass plugin-specific parameters we have used..\n", + "\n", + "## 4- Run plugin\n", + "Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that:\n", + "Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started.\n", + "The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to.\n", + "After that navigator will take over with the behavior tree XML file behavior definition provided to it.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::configure\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'shared_ptr\\n'\n", + " '<\\n'\n", + " 'nav2_util\\n'\n", + " '::\\n'\n", + " 'OdomSmoother\\n'\n", + " '>\\n'\n", + " 'odom_smoother\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'Time\\n'\n", + " '(\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"goal\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"goal_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '(\\n'\n", + " '\"path\"\\n'\n", + " '));\\n'\n", + " '}\\n'\n", + " 'path_blackboard_id_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"path_blackboard_id\"\\n'\n", + " ').\\n'\n", + " 'as_string\\n'\n", + " '();\\n'\n", + " '// Odometry smoother object for getting current speed\\n'\n", + " 'odom_smoother_\\n'\n", + " '=\\n'\n", + " 'odom_smoother\\n'\n", + " ';\\n'\n", + " 'self_client_\\n'\n", + " '=\\n'\n", + " 'rclcpp_action\\n'\n", + " '::\\n'\n", + " 'create_client\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'node\\n'\n", + " ',\\n'\n", + " 'getName\\n'\n", + " '());\\n'\n", + " 'goal_sub_\\n'\n", + " '=\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'create_subscription\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"goal_pose\"\\n'\n", + " ',\\n'\n", + " 'rclcpp\\n'\n", + " '::\\n'\n", + " 'SystemDefaultsQoS\\n'\n", + " '(),\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'bind\\n'\n", + " '(\\n'\n", + " '&\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " '::\\n'\n", + " 'onGoalPoseReceived\\n'\n", + " ',\\n'\n", + " 'this\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'placeholders\\n'\n", + " '::\\n'\n", + " '_1\\n'\n", + " '));\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the Navigate to Pose Navigator,configure()method must '\n", + " 'determine the blackboard parameter names where the goal and '\n", + " 'paths are being stored, as these are key values for processing '\n", + " 'feedback inonLoopand for the different behavior tree nodes to '\n", + " 'communicate this information between themselves. Additionally '\n", + " 'and uniquely to this navigator type, we also create a client to '\n", + " 'itself and a subscription to thegoal_posetopic such that '\n", + " 'requests from the default configurations of Rviz2 using theGoal '\n", + " 'Posetool will be processed.',\n", + " 'filename': 'goal_pose',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::cleanup\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'goal_sub_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'self_client_\\n'\n", + " '.\\n'\n", + " 'reset\\n'\n", + " '();\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'The values of the blackboard IDs are stored alongside the '\n", + " 'odometry smoother the BT Navigator provides for populating '\n", + " 'meaningful feedback later. Complimentary to this, '\n", + " 'thecleanupmethod will reset these resources. The activate and '\n", + " 'deactivate methods are not used in this particular navigator.',\n", + " 'filename': 'cleanup',\n", + " 'language': 'unknown'},\n", + " {'code': 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'NavigateToPoseNavigator::getDefaultBTFilepath\\n'\n", + " '(\\n'\n", + " 'rclcpp_lifecycle\\n'\n", + " '::\\n'\n", + " 'LifecycleNode\\n'\n", + " '::\\n'\n", + " 'WeakPtr\\n'\n", + " 'parent_node\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " 'auto\\n'\n", + " 'node\\n'\n", + " '=\\n'\n", + " 'parent_node\\n'\n", + " '.\\n'\n", + " 'lock\\n'\n", + " '();\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'has_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " 'pkg_share_dir\\n'\n", + " '=\\n'\n", + " 'ament_index_cpp\\n'\n", + " '::\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"nav2_bt_navigator\"\\n'\n", + " ');\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'declare_parameter\\n'\n", + " '<\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'pkg_share_dir\\n'\n", + " '+\\n'\n", + " '\"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml\"\\n'\n", + " ');\\n'\n", + " '}\\n'\n", + " 'node\\n'\n", + " '->\\n'\n", + " 'get_parameter\\n'\n", + " '(\\n'\n", + " '\"default_nav_to_pose_bt_xml\"\\n'\n", + " ',\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'default_bt_xml_filename\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In thegetDefaultBTFilepath(), we use a '\n", + " 'parameterdefault_nav_to_pose_bt_xmlto get the default behavior '\n", + " 'tree XML file to use if none is provided by the navigation '\n", + " 'request and to initialize the BT Navigator with a behavior tree '\n", + " 'hot-loaded. If one is not provided in the parameter files, then '\n", + " 'we grab a known and reasonable default XML file in '\n", + " 'thenav2_bt_navigatorpackage:',\n", + " 'filename': 'nav2_bt_navigator',\n", + " 'language': 'unknown'},\n", + " {'code': 'bool\\n'\n", + " 'NavigateToPoseNavigator::goalReceived\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'bt_xml_filename\\n'\n", + " '=\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " ';\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " '!\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'loadBehaviorTree\\n'\n", + " '(\\n'\n", + " 'bt_xml_filename\\n'\n", + " '))\\n'\n", + " '{\\n'\n", + " 'RCLCPP_ERROR\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"BT file not found: %s. Navigation canceled.\"\\n'\n", + " ',\\n'\n", + " 'bt_xml_filename\\n'\n", + " '.\\n'\n", + " 'c_str\\n'\n", + " '());\\n'\n", + " 'return\\n'\n", + " 'false\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " ');\\n'\n", + " 'return\\n'\n", + " 'true\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'When a goal is received, we need to determine if this goal is '\n", + " 'valid and should be processed.\\n'\n", + " 'ThegoalReceivedmethod provides you thegoaland a return value if '\n", + " 'it is being processed or not. This information is sent back to '\n", + " 'the action server to notify the client. In this case, we want to '\n", + " 'make sure that the goal’s behavior tree is valid or else we '\n", + " 'cannot proceed. If it is valid, then we can initialize the goal '\n", + " 'pose onto the blackboard and reset some state in order to '\n", + " 'cleanly process this new request.',\n", + " 'filename': 'goal',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::goalCompleted\\n'\n", + " '(\\n'\n", + " 'typename\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Result\\n'\n", + " '::\\n'\n", + " 'SharedPtr\\n'\n", + " '/*result*/\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'BtStatus\\n'\n", + " '/*final_bt_status*/\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " '}',\n", + " 'context': 'Once this goal is completed, we need to populate the Action’s '\n", + " 'result, if required and meaningful. In this navigator’s case, it '\n", + " 'contains no result information when the navigation request was '\n", + " 'completed successfully, so this method is empty. For other '\n", + " 'navigator types, you may populate theresultobject provided.',\n", + " 'filename': 'result',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onPreempt\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Received goal preemption request\"\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '||\\n'\n", + " '(\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'behavior_tree\\n'\n", + " '.\\n'\n", + " 'empty\\n'\n", + " '()\\n'\n", + " '&&\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getCurrentBTFilename\\n'\n", + " '()\\n'\n", + " '==\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getDefaultBTFilename\\n'\n", + " '()))\\n'\n", + " '{\\n'\n", + " '// if pending goal requests the same BT as the current goal, accept '\n", + " 'the pending goal\\n'\n", + " '// if pending goal has an empty behavior_tree field, it requests '\n", + " 'the default BT file\\n'\n", + " '// accept the pending goal if the current goal is running the '\n", + " 'default BT file\\n'\n", + " 'initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'acceptPendingGoal\\n'\n", + " '());\\n'\n", + " '}\\n'\n", + " 'else\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Preemption request was rejected since the requested BT XML file is '\n", + " 'not the same \"\\n'\n", + " '\"as the one that the current goal is executing. Preemption with a '\n", + " 'new BT is invalid \"\\n'\n", + " '\"since it would require cancellation of the previous goal instead '\n", + " 'of true preemption.\"\\n'\n", + " '\"\\n'\n", + " '\\\\n\\n'\n", + " 'Cancel the current goal and send a new action request if you want '\n", + " 'to use a \"\\n'\n", + " '\"different BT XML file. For now, continuing to track the last goal '\n", + " 'until completion.\"\\n'\n", + " ');\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'terminatePendingGoal\\n'\n", + " '();\\n'\n", + " '}\\n'\n", + " '}',\n", + " 'context': 'If however a goal is preempted (e.g. a new action request comes '\n", + " 'in while an existing request is being processed), '\n", + " 'theonPreempt()method is called to determine if the new request '\n", + " 'is genuine and appropriate to preempt the currently processing '\n", + " 'goal. For example, it might not be wise to accept a preeemption '\n", + " 'request if that request is fundamentally different in nature '\n", + " 'from an existing behavior tree task or when your existing task '\n", + " 'is of a higher priority.',\n", + " 'filename': 'onPreempt()',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::initializeGoalPose\\n'\n", + " '(\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Goal\\n'\n", + " '::\\n'\n", + " 'ConstSharedPtr\\n'\n", + " 'goal\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_INFO\\n'\n", + " '(\\n'\n", + " 'logger_\\n'\n", + " ',\\n'\n", + " '\"Begin navigating from current location to (%.2f, %.2f)\"\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'x\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'pose\\n'\n", + " '.\\n'\n", + " 'position\\n'\n", + " '.\\n'\n", + " 'y\\n'\n", + " ');\\n'\n", + " '// Reset state for new action feedback\\n'\n", + " 'start_time_\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '();\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " '0\\n'\n", + " ');\\n'\n", + " '// NOLINT\\n'\n", + " '// Update the goal pose on the blackboard\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'set\\n'\n", + " '<\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'goal_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'goal\\n'\n", + " '->\\n'\n", + " 'pose\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Note that here you can also see theinitializeGoalPosemethod '\n", + " 'called. This method will set the goal parameters for this '\n", + " 'navigator onto the blackboard and reset important state '\n", + " 'information to cleanly reuse a behavior tree without old state '\n", + " 'information, as shown below:',\n", + " 'filename': 'initializeGoalPose',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\n'\n", + " 'NavigateToPoseNavigator::onLoop\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'auto\\n'\n", + " 'feedback_msg\\n'\n", + " '=\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_shared\\n'\n", + " '<\\n'\n", + " 'ActionT\\n'\n", + " '::\\n'\n", + " 'Feedback\\n'\n", + " '>\\n'\n", + " '();\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " '...;\\n'\n", + " 'auto\\n'\n", + " 'blackboard\\n'\n", + " '=\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'getBlackboard\\n'\n", + " '();\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'current_path\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'path_blackboard_id_\\n'\n", + " ',\\n'\n", + " 'current_path\\n'\n", + " ');\\n'\n", + " '...\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'distance_remaining\\n'\n", + " '=\\n'\n", + " 'distance_remaining\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'estimated_time_remaining\\n'\n", + " '=\\n'\n", + " 'estimated_time_remaining\\n'\n", + " ';\\n'\n", + " 'int\\n'\n", + " 'recovery_count\\n'\n", + " '=\\n'\n", + " '0\\n'\n", + " ';\\n'\n", + " 'blackboard\\n'\n", + " '->\\n'\n", + " 'get\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"number_recoveries\"\\n'\n", + " ',\\n'\n", + " 'recovery_count\\n'\n", + " ');\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'number_of_recoveries\\n'\n", + " '=\\n'\n", + " 'recovery_count\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'current_pose\\n'\n", + " '=\\n'\n", + " 'current_pose\\n'\n", + " ';\\n'\n", + " 'feedback_msg\\n'\n", + " '->\\n'\n", + " 'navigation_time\\n'\n", + " '=\\n'\n", + " 'clock_\\n'\n", + " '->\\n'\n", + " 'now\\n'\n", + " '()\\n'\n", + " '-\\n'\n", + " 'start_time_\\n'\n", + " ';\\n'\n", + " 'bt_action_server_\\n'\n", + " '->\\n'\n", + " 'publishFeedback\\n'\n", + " '(\\n'\n", + " 'feedback_msg\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'The final function implemented isonLoop, which is simplified '\n", + " 'below for tutorial purposes. While anything can be done in this '\n", + " 'method, which is called as the BT is looping through the tree, '\n", + " 'it is common to use this as an opportunity to populate any '\n", + " 'necessary feedback about the state of the navigation request, '\n", + " 'robot, or metadata that a client might be interested in.',\n", + " 'filename': 'onLoop',\n", + " 'language': 'unknown'},\n", + " {'code': '#include\\n'\n", + " '\"pluginlib/class_list_macros.hpp\"\\n'\n", + " 'PLUGINLIB_EXPORT_CLASS\\n'\n", + " '(\\n'\n", + " 'nav2_bt_navigator\\n'\n", + " '::\\n'\n", + " 'NavigateToPoseNavigator\\n'\n", + " ',\\n'\n", + " 'nav2_core\\n'\n", + " '::\\n'\n", + " 'NavigatorBase\\n'\n", + " ')',\n", + " 'context': 'To export the controller, we need to provide two lines',\n", + " 'filename': 'nav2_core::NavigatorBase',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'This\\n'\n", + " 'is\\n'\n", + " 'pure\\n'\n", + " 'point-to-point\\n'\n", + " 'navigation\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'description: Description of the plugin.',\n", + " 'filename': 'description',\n", + " 'language': 'unknown'},\n", + " {'code': 'pluginlib_export_plugin_description_file(nav2_core '\n", + " 'navigator_plugin.xml)\\n',\n", + " 'context': 'Next step would be to export plugin usingCMakeLists.txtby using '\n", + " 'CMake functionpluginlib_export_plugin_description_file(). This '\n", + " 'function installs the plugin description file tosharedirectory '\n", + " 'and sets ament indexes to make it discoverable.',\n", + " 'filename': 'share',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'ament_cmake\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'The plugin description file should also be added topackage.xml',\n", + " 'filename': 'package.xml',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: true\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' transform_tolerance: 0.1\\n'\n", + " ' default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or '\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml\\n'\n", + " ' default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # '\n", + " 'or $(find-pkg-share '\n", + " 'my_package)/behavior_tree/my_nav_through_poses_bt.xml\\n'\n", + " ' goal_blackboard_id: goal\\n'\n", + " ' goals_blackboard_id: goals\\n'\n", + " ' path_blackboard_id: path\\n'\n", + " \" navigators: ['navigate_to_pose', 'navigate_through_poses']\\n\"\n", + " ' navigate_to_pose:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateToPoseNavigator\" # In '\n", + " 'Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " ' navigate_through_poses:\\n'\n", + " ' plugin: \"nav2_bt_navigator::NavigateThroughPosesNavigator\" # '\n", + " 'In Iron and older versions, \"/\" was used instead of \"::\"\\n',\n", + " 'context': 'To enable the plugin, we need to modify thenav2_params.yamlfile '\n", + " 'as below',\n", + " 'filename': 'nav2_params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'tb3_simulation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '/path/to/your_params_file.yaml\\n',\n", + " 'context': 'Run Turtlebot3 simulation with enabled Nav2. Detailed '\n", + " 'instructions on how to make it run are written atGetting '\n", + " 'Started. Below is a shortcut command for that:',\n", + " 'filename': '.',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Range Sensor Parameters\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "=== Document ===\n", + "Title: Groot - Interacting with Behavior Trees\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Grootis the companion application of theBehaviorTree.CPPlibrary used to create, edit, and visualize behavior trees.\n", + "Behavior Trees are deeply integrated into Nav2, used as the main method of orchestrating task server logic across a complex navigation and autonomy stack.\n", + "Behavior Trees, in short BTs, consist of many nodes completing different tasks and control the flow of logic, similar to a Hierarchical or Finite State Machine, but organized in a tree structure.\n", + "These nodes are of types:Action,Condition,Control, orDecorator, and are described in more detail inNavigation ConceptsandBehaviorTree.CPP.\n", + "Writing a New Behavior Tree Pluginoffers a well written example of creating a simpleActionnode if creating new BT nodes is of interest. This tutorial will focus solely on launching Groot, visualizing a Behavior Tree, and modifying that tree for a given customization, assuming a library of BT nodes. Luckily, Nav2 provides a robust number of BT nodes for your use out of the box, enumerated inNavigation Plugins.\n", + "A BT configuration file in BehaviorTree.CPP is an XML file. This is used to dynamically load the BT node plugins at run-time from the appropriate libraries mapped to their names. The XML format is definedin detail here. Therefore, Groot needs to have a list of nodes it has access to and important metadata about them like their type and ports (or parameters). We refer to this as the “palette” of nodes later in the tutorial.\n", + "In the video above you can see Groot side-by-side with RVIz and a test platform 100% equipped with ROS-enabled hardware from SIEMENS.\n", + "Groot not only displays the current Behavior Tree while the robot is operating. Note: Before ROS 2 Humble, live Groot behavior tree monitoring during execution was supported in Nav2. This was removed due to buggy support in BT.CPP / Groot for changing behavior trees on the fly, seeGalactic to Humblefor more details.\n", + "\n", + "## Visualize Behavior Trees\n", + "To display a Behavior Tree like that inFigure 3, we will first start the Groot executable.\n", + "Out of the box, Groot can only display Behavior Trees and nodes that are from the defaults in BT.CPP, since it does not know anything about Nav2 or your other projects.\n", + "Therefore, we must point Groot to our palette, or index, of Nav2 / custom behavior tree nodes:\n", + "If you select the default treenavigate_w_replanning_and_recovery.xml, then a Groot editor should look likeFigure 3.\n", + "\n", + "## Edit Behavior Trees\n", + "Now that you have a Nav2 BT open in Groot in editor mode, you should be able to trivially modify it using the GUI.\n", + "Starting from a screen like that shown inFigure 3, you can pull in new nodes from the side panel to add them to the workspace.\n", + "You may then connect the nodes using a “drag and drop” motion between the node’s input and output ports to assemble the new nodes into the tree.\n", + "If you select a given node, you can change metadata about it such as its name or values of parameterizable ports. When you’re done modifying, simply save the new configuration file and use that on your robot the next time!\n", + "\n", + "## Adding A Custom Node\n", + "Each node in the behavior tree holds a specialized function.\n", + "Sometimes, its useful to create new nodes and add them to your palette during the design process - perhaps before the implementations themselves exist.\n", + "This helps designers abstract away the implementation specifics of the nodes from the higher level logic of the tree itself and how they’d like to interact with a given node (e.g. type, ports, etc).\n", + "Within Groot, you may create new custom nodes to add to your tree and export these new nodes back to your palette.\n", + "Implementing the node itself needs to be done separately from Groot, which is described inWriting a New Behavior Tree Plugin.\n", + "Creating a new custom node can be started by clicking the orange marked icon inFigure 4, while Groot is in Editor mode.\n", + "This should load a new window, similar toFigure 5.\n", + "In this new window, it asks you to fill in the metadata about this new node, in order to create it.\n", + "It will ask you for standard information such as name (green box), type of node (orange box), and any optional ports for parameterization or access to blackboard variables (blue box).\n", + "After completing, selectOKinFigure 5, the new custom node should appear in blue in theTreeNode Paletteas inFigure 6.\n", + "Before starting to create a new BT based on the new custom nodes, it is recommend to export the newly created nodes to save in case of Groot crashing.\n", + "This can be performed with the icon highlighted in green fromFigure 6.\n", + "The resulting XML output from the node created inFigure 5can be seen below.\n", + "You can see more examples inNav2’s BT Node Palette XML.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'coffee\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Sense\\n'\n", + " 'of\\n'\n", + " 'life\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rolling\\n'\n", + " 'target\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Before starting to create a new BT based on the new custom '\n", + " 'nodes, it is recommend to export the newly created nodes to save '\n", + " 'in case of Groot crashing.\\n'\n", + " 'This can be performed with the icon highlighted in green '\n", + " 'fromFigure 6.\\n'\n", + " 'The resulting XML output from the node created inFigure 5can be '\n", + " 'seen below.\\n'\n", + " 'You can see more examples inNav2’s BT Node Palette XML.',\n", + " 'filename': 'Action',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: GloballyUpdatedGoal\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Vector of goals to check. Takes in a blackboard variable, '\n", + " '“{goals}” if not specified.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Graceful Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Graceful Controller Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '20.0\\n'\n", + " 'min_x_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'min_y_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'min_theta_velocity_threshold\\n'\n", + " ':\\n'\n", + " '0.001\\n'\n", + " 'progress_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"progress_checker\"\\n'\n", + " ']\\n'\n", + " '# progress_checker_plugin: \"progress_checker\" For Humble and older\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"goal_checker\"\\n'\n", + " ']\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'progress_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleProgressChecker\"\\n'\n", + " 'required_movement_radius\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'movement_time_allowance\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'stateful\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " 'nav2_graceful_controller::GracefulController\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'motion_target_dist\\n'\n", + " ':\\n'\n", + " '0.6\\n'\n", + " 'initial_rotation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'initial_rotation_min_angle\\n'\n", + " ':\\n'\n", + " '0.75\\n'\n", + " 'final_rotation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'allow_backward\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'beta\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'lambda\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'v_angular_max\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'slowdown_radius\\n'\n", + " ':\\n'\n", + " '1.5',\n", + " 'context': 'Whether to allow the robot to move backward.',\n", + " 'filename': 'initial_rotation',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Transformations\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Transforms Introduction\n", + "Many ROS packages require the transform tree of a robot to be published using the TF2 ROS package. A transformation tree defines the relations between different coordinate systems, in terms of translation, rotation, and relative motion. To make this more concrete, let us apply an example of a simple robot that has a mobile base with a single laser sensor mounted on top of it.\n", + "This robot has two defined coordinate frames: one corresponding to the center point of the mobile base of the robot, and one for the center point of the laser that is mounted on top of the base. We’ll call the coordinate frame attached to the mobile basebase_linkand we’ll call the coordinate frame attached to the laserbase_laser. Note that will be talking more about the naming and conventions of these coordinate frames in the next section.\n", + "At this point, let’s assume that we have some data from the laser in the form of distance measurements from the laser’s center point. In other words, we have some data in thebase_lasercoordinate frame.\n", + "Now, suppose we want to take this data and use it to help the mobile base avoid obstacles in the world. To do this successfully, we need a way to transform the laser scan we’ve received from thebase_laserframe to thebase_linkframe. In essence, we need to define a relationship between thebase_laserandbase_linkcoordinate frames.\n", + "In defining this relationship, let us assume that the only data we have is that the laser is mounted 10cm forward and 20cm above the center point of the mobile base. This gives us a translational offset that relates thebase_linkframe to thebase_laserframe. Specifically, we know that to get data from thebase_linkframe to thebase_laserframe, we must apply a translation of (x: 0.1m, y: 0.0m, z: 0.2m), and transversely, to get data from thebase_laserframe to thebase_linkframe, we must apply the opposite translation (x: -0.1m, y: 0.0m, z: -0.20m).\n", + "We could choose to manage this relationship ourselves, meaning to store and apply the appropriate translations between the frames when necessary, but this becomes a real pain as the number of coordinate frames increases. Luckily, we don’t have to do this work ourselves. Instead, we’ll define the relationship betweenbase_linkandbase_laseronce using TF2 and let it manage the transformation between the two coordinate frames for us. This is especially useful when working with non-static transformations, such as a set of frames that are moving relative to each other, like a robot base frame in a map frame.\n", + "To define and store the relationship between thebase_linkandbase_laserframes using TF2, we need to add them to a transform tree. Conceptually, each node in the transform tree corresponds to a coordinate frame, and each edge corresponds to the transform that needs to be applied to move from the current node to its child. TF2 uses a tree structure to guarantee that there is only a single traversal that links any two coordinate frames together, and assumes that all edges in the tree are directed from parent to child nodes.\n", + "To create a transform tree for our simple example, we’ll create two nodes: one for thebase_linkcoordinate frame and one for thebase_lasercoordinate frame. To create the edge between them, we first need to decide which node will be the parent and which will be the child. Remember — this distinction is important because TF2 assumes that all transforms move from parent to child.\n", + "Let’s choose thebase_linkcoordinate frame as the parent because when other pieces/sensors are added to the robot, it will make the most sense for them to relate to thebase_laserframe by traversing through thebase_linkframe. This means that the transform associated with the edge connectingbase_linkandbase_lasershould be (x: 0.1m, y: 0.0m, z: 0.2m).\n", + "With this transform tree set up, converting the laser scan received in thebase_laserframe to thebase_linkframe is as simple as making a call to the TF2 library. Our robot can now use this information to reason about laser scans in thebase_linkframe and safely plan around obstacles in its environment.\n", + "\n", + "## Static Transform Publisher Demo\n", + "Now let’s try publishing a very simple transform using the static_transform_publisher tool provided by TF2. We will be publishing a transformation from the linkbase_linkto the linkbase_laserwith a translation of (x: 0.1m, y: 0.0m, z: 0.2m). Note that we will be building the transform from the diagram earlier in this tutorial.\n", + "Open up your command line and execute the following command:\n", + "With this, we are now successfully publishing ourbase_linktobase_lasertransform in TF2. Let us now check if it is working properly throughtf2_echo. Open up a separate command line window and execute the following:\n", + "You should be able to observe a repeated output similar to the one below.\n", + "And that’s it for this short demo - we were able to successfully publish a transform frombase_linktobase_laserusing the TF2 library. Note that we do not recommend using the above demo in publishing transforms for your actual robotics projects, it is just a quick demo to see TF2 in action. For a real robot system, we would create a URDF file which embeds this information and more about your robot for use of the robot_state_publisher rather than the static_transform_publisher. There are more suitable and practical ways to go about this which will be discussed in theSetting Up The URDFtutorial.\n", + "\n", + "## Transforms in Navigation2\n", + "There are two important ROS REPs which we highly suggest for you to check out. These documents detail some standards set about by the ROS community to ensure proper operation across different packages. Nav2 also adheres to these standards and conventions.\n", + "To quickly summarize REP 105, this document specifies the naming conventions and semantic meanings of the different coordinate frames used in ROS. Of interest to this tutorial are thebase_link,odomandmapcoordinate frames. Thebase_linkis a coordinate frame that is attached to a fixed position on the robot, typically at its main chassis and its rotational center. Theodomcoordinate frame is a fixed frame relative to the robot’s starting position and is mainly used for locally-consistent representations of distances. Lastly, themapcoordinate frame is a world fixed frame that is used for globally-consistent representations of distances.\n", + "REP 103, on the other hand, discusses some standard units of measure and other related conventions to keep integration issues between different ROS packages to a minimum. The basic overview is that frames are defined using the right hand rule, with Z up and X forward, and units should be standard SI units.\n", + "Now let’s move on to some specifics for the Navigation2 package to function correctly. Nav2 requires the following transformations to be published in ROS:\n", + "The first transformmap=>odomis usually provided by a different ROS package dealing with localization and mapping such as AMCL. This transform updates live in use so we don’t set static values for this in our robot’s TF tree. Further detail about how to set this up may be pretty complex, so we highly suggest to have a look at the documentation of the mapping or localization package you are using for your platform. All ROS compliant SLAM and localization packages will provide you with this transformation automatically on launch.\n", + "Theodom=>base_linkis usually published by our odometry system using sensors such as wheel encoders. This is typically computed via sensor fusion of odometry sensors (IMU, wheel encoders, VIO, etc) using therobot_localizationpackage.\n", + "All other statically defined transforms (e.g.base_link=>base_laser,base_link=>wheels,wheels=>IMU, etc) is what we will be talking about for the rest of this guide. This transformation tree is used by Nav2 to properly relate the information from sensors or other frame of interest to the rest of the robot. The transformation between these two coordinate frames is usually provided to Nav2 through the Robot State Publisher and the Universal Robot Descriptor File (URDF). In cases where there are more sensor coordinate frames on your platform, then a transform tree frombase_linkto each sensor coordinate frame needs to be published.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed about the concept of transforms and how they are used in Nav2.\n", + "In the last section, we have also explored using the static_transform_publisher of TF2 to publish our transforms. You may use this to set up your transforms for Nav2, but this is generally not the best way to do it. In most robotics projects, we make use of the Robot State Publisher since it is much easier to use and scales well as our robot gets more complex. We will be talking about the Robot State Publisher, URDF, and how to set it up in the next tutorial onSetting Up The URDF.\n", + "Lastly, we also discussed the three published transform requirements of Nav2 and the necessary REPs to keep in mind when setting them up.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '.1\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '.2\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'base_link\\n'\n", + " 'base_laser\\n',\n", + " 'context': 'Open up your command line and execute the following command:',\n", + " 'filename': 'base_laser',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nbase_link\\nbase_laser\\n',\n", + " 'context': 'With this, we are now successfully publishing '\n", + " 'ourbase_linktobase_lasertransform in TF2. Let us now check if it '\n", + " 'is working properly throughtf2_echo. Open up a separate command '\n", + " 'line window and execute the following:',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '0\\n'\n", + " '.0\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.100,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.200\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '1\\n'\n", + " '.000\\n'\n", + " ']',\n", + " 'context': 'You should be able to observe a repeated output similar to the '\n", + " 'one below.',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Transformations\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Transforms Introduction\n", + "Many ROS packages require the transform tree of a robot to be published using the TF2 ROS package. A transformation tree defines the relations between different coordinate systems, in terms of translation, rotation, and relative motion. To make this more concrete, let us apply an example of a simple robot that has a mobile base with a single laser sensor mounted on top of it.\n", + "This robot has two defined coordinate frames: one corresponding to the center point of the mobile base of the robot, and one for the center point of the laser that is mounted on top of the base. We’ll call the coordinate frame attached to the mobile basebase_linkand we’ll call the coordinate frame attached to the laserbase_laser. Note that will be talking more about the naming and conventions of these coordinate frames in the next section.\n", + "At this point, let’s assume that we have some data from the laser in the form of distance measurements from the laser’s center point. In other words, we have some data in thebase_lasercoordinate frame.\n", + "Now, suppose we want to take this data and use it to help the mobile base avoid obstacles in the world. To do this successfully, we need a way to transform the laser scan we’ve received from thebase_laserframe to thebase_linkframe. In essence, we need to define a relationship between thebase_laserandbase_linkcoordinate frames.\n", + "In defining this relationship, let us assume that the only data we have is that the laser is mounted 10cm forward and 20cm above the center point of the mobile base. This gives us a translational offset that relates thebase_linkframe to thebase_laserframe. Specifically, we know that to get data from thebase_linkframe to thebase_laserframe, we must apply a translation of (x: 0.1m, y: 0.0m, z: 0.2m), and transversely, to get data from thebase_laserframe to thebase_linkframe, we must apply the opposite translation (x: -0.1m, y: 0.0m, z: -0.20m).\n", + "We could choose to manage this relationship ourselves, meaning to store and apply the appropriate translations between the frames when necessary, but this becomes a real pain as the number of coordinate frames increases. Luckily, we don’t have to do this work ourselves. Instead, we’ll define the relationship betweenbase_linkandbase_laseronce using TF2 and let it manage the transformation between the two coordinate frames for us. This is especially useful when working with non-static transformations, such as a set of frames that are moving relative to each other, like a robot base frame in a map frame.\n", + "To define and store the relationship between thebase_linkandbase_laserframes using TF2, we need to add them to a transform tree. Conceptually, each node in the transform tree corresponds to a coordinate frame, and each edge corresponds to the transform that needs to be applied to move from the current node to its child. TF2 uses a tree structure to guarantee that there is only a single traversal that links any two coordinate frames together, and assumes that all edges in the tree are directed from parent to child nodes.\n", + "To create a transform tree for our simple example, we’ll create two nodes: one for thebase_linkcoordinate frame and one for thebase_lasercoordinate frame. To create the edge between them, we first need to decide which node will be the parent and which will be the child. Remember — this distinction is important because TF2 assumes that all transforms move from parent to child.\n", + "Let’s choose thebase_linkcoordinate frame as the parent because when other pieces/sensors are added to the robot, it will make the most sense for them to relate to thebase_laserframe by traversing through thebase_linkframe. This means that the transform associated with the edge connectingbase_linkandbase_lasershould be (x: 0.1m, y: 0.0m, z: 0.2m).\n", + "With this transform tree set up, converting the laser scan received in thebase_laserframe to thebase_linkframe is as simple as making a call to the TF2 library. Our robot can now use this information to reason about laser scans in thebase_linkframe and safely plan around obstacles in its environment.\n", + "\n", + "## Static Transform Publisher Demo\n", + "Now let’s try publishing a very simple transform using the static_transform_publisher tool provided by TF2. We will be publishing a transformation from the linkbase_linkto the linkbase_laserwith a translation of (x: 0.1m, y: 0.0m, z: 0.2m). Note that we will be building the transform from the diagram earlier in this tutorial.\n", + "Open up your command line and execute the following command:\n", + "With this, we are now successfully publishing ourbase_linktobase_lasertransform in TF2. Let us now check if it is working properly throughtf2_echo. Open up a separate command line window and execute the following:\n", + "You should be able to observe a repeated output similar to the one below.\n", + "And that’s it for this short demo - we were able to successfully publish a transform frombase_linktobase_laserusing the TF2 library. Note that we do not recommend using the above demo in publishing transforms for your actual robotics projects, it is just a quick demo to see TF2 in action. For a real robot system, we would create a URDF file which embeds this information and more about your robot for use of the robot_state_publisher rather than the static_transform_publisher. There are more suitable and practical ways to go about this which will be discussed in theSetting Up The URDFtutorial.\n", + "\n", + "## Transforms in Navigation2\n", + "There are two important ROS REPs which we highly suggest for you to check out. These documents detail some standards set about by the ROS community to ensure proper operation across different packages. Nav2 also adheres to these standards and conventions.\n", + "To quickly summarize REP 105, this document specifies the naming conventions and semantic meanings of the different coordinate frames used in ROS. Of interest to this tutorial are thebase_link,odomandmapcoordinate frames. Thebase_linkis a coordinate frame that is attached to a fixed position on the robot, typically at its main chassis and its rotational center. Theodomcoordinate frame is a fixed frame relative to the robot’s starting position and is mainly used for locally-consistent representations of distances. Lastly, themapcoordinate frame is a world fixed frame that is used for globally-consistent representations of distances.\n", + "REP 103, on the other hand, discusses some standard units of measure and other related conventions to keep integration issues between different ROS packages to a minimum. The basic overview is that frames are defined using the right hand rule, with Z up and X forward, and units should be standard SI units.\n", + "Now let’s move on to some specifics for the Navigation2 package to function correctly. Nav2 requires the following transformations to be published in ROS:\n", + "The first transformmap=>odomis usually provided by a different ROS package dealing with localization and mapping such as AMCL. This transform updates live in use so we don’t set static values for this in our robot’s TF tree. Further detail about how to set this up may be pretty complex, so we highly suggest to have a look at the documentation of the mapping or localization package you are using for your platform. All ROS compliant SLAM and localization packages will provide you with this transformation automatically on launch.\n", + "Theodom=>base_linkis usually published by our odometry system using sensors such as wheel encoders. This is typically computed via sensor fusion of odometry sensors (IMU, wheel encoders, VIO, etc) using therobot_localizationpackage.\n", + "All other statically defined transforms (e.g.base_link=>base_laser,base_link=>wheels,wheels=>IMU, etc) is what we will be talking about for the rest of this guide. This transformation tree is used by Nav2 to properly relate the information from sensors or other frame of interest to the rest of the robot. The transformation between these two coordinate frames is usually provided to Nav2 through the Robot State Publisher and the Universal Robot Descriptor File (URDF). In cases where there are more sensor coordinate frames on your platform, then a transform tree frombase_linkto each sensor coordinate frame needs to be published.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed about the concept of transforms and how they are used in Nav2.\n", + "In the last section, we have also explored using the static_transform_publisher of TF2 to publish our transforms. You may use this to set up your transforms for Nav2, but this is generally not the best way to do it. In most robotics projects, we make use of the Robot State Publisher since it is much easier to use and scales well as our robot gets more complex. We will be talking about the Robot State Publisher, URDF, and how to set it up in the next tutorial onSetting Up The URDF.\n", + "Lastly, we also discussed the three published transform requirements of Nav2 and the necessary REPs to keep in mind when setting them up.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '.1\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '.2\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'base_link\\n'\n", + " 'base_laser\\n',\n", + " 'context': 'Open up your command line and execute the following command:',\n", + " 'filename': 'base_laser',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_ros\\ntf2_echo\\nbase_link\\nbase_laser\\n',\n", + " 'context': 'With this, we are now successfully publishing '\n", + " 'ourbase_linktobase_lasertransform in TF2. Let us now check if it '\n", + " 'is working properly throughtf2_echo. Open up a separate command '\n", + " 'line window and execute the following:',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'},\n", + " {'code': 'At\\n'\n", + " 'time\\n'\n", + " '0\\n'\n", + " '.0\\n'\n", + " '-\\n'\n", + " 'Translation:\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.100,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.200\\n'\n", + " ']\\n'\n", + " '\\n'\n", + " '-\\n'\n", + " 'Rotation:\\n'\n", + " 'in\\n'\n", + " 'Quaternion\\n'\n", + " '[\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '0\\n'\n", + " '.000,\\n'\n", + " '1\\n'\n", + " '.000\\n'\n", + " ']',\n", + " 'context': 'You should be able to observe a repeated output similar to the '\n", + " 'one below.',\n", + " 'filename': 'tf2_echo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Groot - Interacting with Behavior Trees\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "Grootis the companion application of theBehaviorTree.CPPlibrary used to create, edit, and visualize behavior trees.\n", + "Behavior Trees are deeply integrated into Nav2, used as the main method of orchestrating task server logic across a complex navigation and autonomy stack.\n", + "Behavior Trees, in short BTs, consist of many nodes completing different tasks and control the flow of logic, similar to a Hierarchical or Finite State Machine, but organized in a tree structure.\n", + "These nodes are of types:Action,Condition,Control, orDecorator, and are described in more detail inNavigation ConceptsandBehaviorTree.CPP.\n", + "Writing a New Behavior Tree Pluginoffers a well written example of creating a simpleActionnode if creating new BT nodes is of interest. This tutorial will focus solely on launching Groot, visualizing a Behavior Tree, and modifying that tree for a given customization, assuming a library of BT nodes. Luckily, Nav2 provides a robust number of BT nodes for your use out of the box, enumerated inNavigation Plugins.\n", + "A BT configuration file in BehaviorTree.CPP is an XML file. This is used to dynamically load the BT node plugins at run-time from the appropriate libraries mapped to their names. The XML format is definedin detail here. Therefore, Groot needs to have a list of nodes it has access to and important metadata about them like their type and ports (or parameters). We refer to this as the “palette” of nodes later in the tutorial.\n", + "In the video above you can see Groot side-by-side with RVIz and a test platform 100% equipped with ROS-enabled hardware from SIEMENS.\n", + "Groot not only displays the current Behavior Tree while the robot is operating. Note: Before ROS 2 Humble, live Groot behavior tree monitoring during execution was supported in Nav2. This was removed due to buggy support in BT.CPP / Groot for changing behavior trees on the fly, seeGalactic to Humblefor more details.\n", + "\n", + "## Visualize Behavior Trees\n", + "To display a Behavior Tree like that inFigure 3, we will first start the Groot executable.\n", + "Out of the box, Groot can only display Behavior Trees and nodes that are from the defaults in BT.CPP, since it does not know anything about Nav2 or your other projects.\n", + "Therefore, we must point Groot to our palette, or index, of Nav2 / custom behavior tree nodes:\n", + "If you select the default treenavigate_w_replanning_and_recovery.xml, then a Groot editor should look likeFigure 3.\n", + "\n", + "## Edit Behavior Trees\n", + "Now that you have a Nav2 BT open in Groot in editor mode, you should be able to trivially modify it using the GUI.\n", + "Starting from a screen like that shown inFigure 3, you can pull in new nodes from the side panel to add them to the workspace.\n", + "You may then connect the nodes using a “drag and drop” motion between the node’s input and output ports to assemble the new nodes into the tree.\n", + "If you select a given node, you can change metadata about it such as its name or values of parameterizable ports. When you’re done modifying, simply save the new configuration file and use that on your robot the next time!\n", + "\n", + "## Adding A Custom Node\n", + "Each node in the behavior tree holds a specialized function.\n", + "Sometimes, its useful to create new nodes and add them to your palette during the design process - perhaps before the implementations themselves exist.\n", + "This helps designers abstract away the implementation specifics of the nodes from the higher level logic of the tree itself and how they’d like to interact with a given node (e.g. type, ports, etc).\n", + "Within Groot, you may create new custom nodes to add to your tree and export these new nodes back to your palette.\n", + "Implementing the node itself needs to be done separately from Groot, which is described inWriting a New Behavior Tree Plugin.\n", + "Creating a new custom node can be started by clicking the orange marked icon inFigure 4, while Groot is in Editor mode.\n", + "This should load a new window, similar toFigure 5.\n", + "In this new window, it asks you to fill in the metadata about this new node, in order to create it.\n", + "It will ask you for standard information such as name (green box), type of node (orange box), and any optional ports for parameterization or access to blackboard variables (blue box).\n", + "After completing, selectOKinFigure 5, the new custom node should appear in blue in theTreeNode Paletteas inFigure 6.\n", + "Before starting to create a new BT based on the new custom nodes, it is recommend to export the newly created nodes to save in case of Groot crashing.\n", + "This can be performed with the icon highlighted in green fromFigure 6.\n", + "The resulting XML output from the node created inFigure 5can be seen below.\n", + "You can see more examples inNav2’s BT Node Palette XML.\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'coffee\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'Sense\\n'\n", + " 'of\\n'\n", + " 'life\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'rolling\\n'\n", + " 'target\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Before starting to create a new BT based on the new custom '\n", + " 'nodes, it is recommend to export the newly created nodes to save '\n", + " 'in case of Groot crashing.\\n'\n", + " 'This can be performed with the icon highlighted in green '\n", + " 'fromFigure 6.\\n'\n", + " 'The resulting XML output from the node created inFigure 5can be '\n", + " 'seen below.\\n'\n", + " 'You can see more examples inNav2’s BT Node Palette XML.',\n", + " 'filename': 'Action',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Getting Involved\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Getting Involved\n", + "If you’re interested in getting involved in Navigation 2, first of all, welcome!\n", + "We encourage everyone to get involved from students, to junior developers, to senior developers, and executives.\n", + "There’s something to do for everyone from bug fixes, to feature development, new algorithms, and refactoring.\n", + "All ROS 2 TSC Working Groups have their meetings on theworking group calendar.\n", + "Here, you can find the date and time of the Navigation2 working group meeting. Make sure you’re checking in your local timezone.\n", + "From this calendar, you can add yourself to the event so it will appear on your google calendar and get the event link to the call through Google Hangouts.\n", + "We encourage everyone interested to come to the meeting to introduce yourself, your project, and see what everyone is working on.\n", + "Further,ROS Discourseis a good place to follow larger discussions happening in the community and announcements. This isnotthe correct place to post questions or ask for assistance. Please visitROS Answersfor Q&A.\n", + "Lastly, we have aCommunity Slackwhere we chat in real-time about topics in public channels or sidebar maintainers on individual projects via PMs. If you’re interested in contributing to Nav2, this is a great place to join!\n", + "If you’re looking to contribute code or bugs, please see the Process section below.\n", + "Over time, for developers that have an interest and have shown technical competence in an area of the stack, we elevate developers to a maintainers status.\n", + "That allows push rights to our protected branches, first-reviewers rights, and getting your name onAbout and Contact.\n", + "There currently is not a clear process for getting to be a maintainer, but if you’ve been involved and contributing over a duration of several months, you may be a good candidate and should email the project lead listed onAbout and Contact.\n", + "\n", + "## Process\n", + "After you’ve introduced yourself in a working group meeting (recommended, not required), you’re ready to get started!\n", + "We recommend a typical open-source project flow and value detail and transparency.\n", + "If you commit to something and need to pull back, say so.\n", + "We all know priorities change and appreciate the heads up so that task can go into the open queue of tasks.\n", + "The process is simple and is as follow:\n", + "Note: We take code quality seriously and strive for high-quality and consistent code.\n", + "We make use of the linting and static analysis tools provided in ROS 2 (ament_cpplint,ament_uncrustify,ament_cppcheck, etc).\n", + "All PRs are built in CI with the appropriate ROS distributions and run through a set of unit and system level tests including static analysis.\n", + "You can see the results of these tests in the pull request.\n", + "It is expected for feature development for tests to cover this work to be added.\n", + "If any documentation must be updated due to your changes, that should be included in your pull request.\n", + "\n", + "## Licensing\n", + "Licensing is very important to open source projects. It helps ensure the\n", + "software continues to be available under the terms that the author\n", + "desired.\n", + "Because much of the source code is ported from other ROS 1 projects, each\n", + "package has it’s own license. Contributions should be made under the predominant\n", + "license of that package. Entirely new packages should be made available under\n", + "theApache 2.0 license.\n", + "A license tells you what rights you have as a developer, as provided by\n", + "the copyright holder. It is important that the contributor fully\n", + "understands the licensing rights and agrees to them. Sometimes the\n", + "copyright holder isn’t the contributor, such as when the contributor is\n", + "doing work on behalf of a company.\n", + "If for some reason Apache 2.0 or BSD licenses are not appropriate for your work, please get in contact with a project maintainer and discuss your concerns or requirements.\n", + "We may consider special exceptions for exceptional work, within reason (we will not accept any licenses that makes it unsuitable for commercial use).\n", + "\n", + "## Developer Certification of Origin (DCO)\n", + "To make a good faith effort to ensure licensing criteria are met,\n", + "Nav2 encourages the Developer Certificate of Origin (DCO) process\n", + "to be followed.\n", + "The DCO is an attestation attached to every contribution made by a\n", + "developer. In the commit message of the contribution, (described more\n", + "fully later in this document), the developer simply adds aSigned-off-bystatement and thereby agrees to the DCO.\n", + "In practice, its easier to justgitcommit-s-m\"commitmessage.\".\n", + "Where-sadds this automatically.\n", + "If you forgot to add this to a commit, it is easy to append via:gitcommit--amend-s.\n", + "When a developer submits a patch, it is a commitment that the\n", + "contributor has the right to submit the patch per the license. The DCO\n", + "agreement is shown below and athttp://developercertificate.org/.\n", + "\n", + "Code Blocks:\n", + "[{'code': \"Developer's Certificate of Origin 1.1\\n\"\n", + " '\\n'\n", + " 'By making a contribution to this project, I certify that:\\n'\n", + " '\\n'\n", + " '(a) The contribution was created in whole or in part by me and I\\n'\n", + " ' have the right to submit it under the open source license\\n'\n", + " ' indicated in the file; or\\n'\n", + " '\\n'\n", + " '(b) The contribution is based upon previous work that, to the\\n'\n", + " ' best of my knowledge, is covered under an appropriate open\\n'\n", + " ' source license and I have the right under that license to\\n'\n", + " ' submit that work with modifications, whether created in whole\\n'\n", + " ' or in part by me, under the same open source license (unless\\n'\n", + " ' I am permitted to submit under a different license), as\\n'\n", + " ' Indicated in the file; or\\n'\n", + " '\\n'\n", + " '(c) The contribution was provided directly to me by some other\\n'\n", + " ' person who certified (a), (b) or (c) and I have not modified\\n'\n", + " ' it.\\n'\n", + " '\\n'\n", + " '(d) I understand and agree that this project and the contribution\\n'\n", + " ' are public and that a record of the contribution (including\\n'\n", + " ' all personal information I submit with it, including my\\n'\n", + " ' sign-off) is maintained indefinitely and may be redistributed\\n'\n", + " ' consistent with this project or the open source license(s)\\n'\n", + " ' involved.\\n',\n", + " 'context': 'When a developer submits a patch, it is a commitment that the\\n'\n", + " 'contributor has the right to submit the patch per the license. '\n", + " 'The DCO\\n'\n", + " 'agreement is shown below and athttp://developercertificate.org/.',\n", + " 'filename': 'gitcommit--amend-s',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Using Docking Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to use the Docking Server with Nav2 robot systems.\n", + "The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them.\n", + "This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started.\n", + "A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions.\n", + "Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking.\n", + "These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations.\n", + "It is likely that you may be able to use this as well rather than developing your own dock plugin to get started.\n", + "The docking procedure is as follows:\n", + "Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial!\n", + "You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package!\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking.\n", + "Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference.\n", + "Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs.\n", + "\n", + "## ChargingDock Plugins\n", + "opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework.\n", + "This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made.\n", + "Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics.\n", + "However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use.\n", + "The plugins has a few key APIs:\n", + "TheSimpleChargingDockprovides an implementation with common options for these APIs:\n", + "Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used.\n", + "It can also be used when only some of the information if available as well.\n", + "If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs.\n", + "However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started.\n", + "There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs.\n", + "If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started.\n", + "Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds.\n", + "The defaults support this out of the box, seenova_carter_dockingfor an example.\n", + "\n", + "## Dock Database\n", + "To dock your robot, you must provide the set of docks in your environment you’d like to utilize.\n", + "This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins.\n", + "The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space.\n", + "The docks plugins must be provided in your docking server’s configuration file.\n", + "However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment.\n", + "The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks.\n", + "The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them.\n", + "Please update these with your own docking plugin and dock locations in your map.\n", + "The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter.\n", + "Note that you are required to provide at least 1 dock plugin and 1 dock instance.\n", + "The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration.\n", + "If you plan to only use this API, you can set adummy_dock.\n", + "Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets.\n", + "The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location.\n", + "\n", + "## Configuring Docking Server\n", + "Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server.\n", + "For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage.\n", + "For a full list of parameters and their descriptions, check out theDocking Server.\n", + "Below is an example configuration used by the Nova Carter robot.\n", + "Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure.\n", + "We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile.\n", + "The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging.\n", + "This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error.\n", + "Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose.\n", + "This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature.\n", + "In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose.\n", + "Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging.\n", + "The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt.\n", + "\n", + "## Adding Docking Server to Launch\n", + "This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file).\n", + "\n", + "## Docking Action API\n", + "The API for docking and undocking is comparatively simple.\n", + "TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action.\n", + "If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like.\n", + "If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database.\n", + "This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended.\n", + "Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time.\n", + "In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted.\n", + "During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries.\n", + "The feedback can be obtained from your action client if this information is useful to your application.\n", + "TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock).\n", + "It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs.\n", + "\n", + "## Putting It All Together\n", + "At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors.\n", + "You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher.\n", + "If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you.\n", + "If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc.\n", + "We can test this using the scriptdemo.pyinnova_carter_docking’s root directory.\n", + "It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row.\n", + "This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system.\n", + "See the video below of this all at work!\n", + "Note that the robot is able to overcome:\n", + "This script demonstrates the essential use of the Docking Server.\n", + "However, it does not use the dock database of pre-mapped dock locations that you setup.\n", + "After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead:\n", + "Then, we can see the full docking system in action in a non-trivial environment!\n", + "Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking.\n", + "If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately.\n", + "You can see both of these in action in the video above.\n", + "Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample.\n", + "Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2.\n", + "If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal).\n", + "However, you can always callUndockRobotfrom any behavior tree!\n", + "Happy docking!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " '# More parameters exist here that we will discuss later in the '\n", + " 'tutorial\\n'\n", + " '# Dock instances\\n'\n", + " 'docks\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'home_dock'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock1'\\n\"\n", + " ',\\n'\n", + " \"'flex_dock2'\\n\"\n", + " ']\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " 'frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '30.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " '# Or use\\n'\n", + " '# dock_database: /my/path/to/dock_database.yaml',\n", + " 'context': 'The docks plugins must be provided in your docking server’s '\n", + " 'configuration file.\\n'\n", + " 'However, the dock instance may be provided either in the '\n", + " 'configuration fileorwithin a provided filepath to decouple the '\n", + " 'server’s configuration from a particular application '\n", + " 'environment.\\n'\n", + " 'The example below shows an inline configuration of the docking '\n", + " 'plugins and dock instances where one dock type '\n", + " '(nova_carter_dock) is specified with 3 individual instances: a '\n", + " 'home dock, and 2 general shared fallback docks.\\n'\n", + " 'The docks can be specified as[x,y,theta]in any reference frame '\n", + " 'you like, as long as TF is aware of them.\\n'\n", + " 'Please update these with your own docking plugin and dock '\n", + " 'locations in your map.',\n", + " 'filename': '[x,y,theta]',\n", + " 'language': 'unknown'},\n", + " {'code': 'docks\\n'\n", + " ':\\n'\n", + " 'home_dock\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock1\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '10.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']\\n'\n", + " 'flex_dock2\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"nova_carter_dock\"\\n'\n", + " 'frame\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'pose\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '20.0\\n'\n", + " ',\\n'\n", + " '0.0\\n'\n", + " ']',\n", + " 'context': 'The analog of this is shown below as an '\n", + " 'independentdock_database.yamlwhich can be provided to '\n", + " 'thedocking_servervia thedock_databaseparameter.',\n", + " 'filename': 'dock_database',\n", + " 'language': 'unknown'},\n", + " {'code': 'docking_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '50.0\\n'\n", + " 'initial_perception_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'wait_charge_timeout\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'dock_approach_timeout\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'undock_linear_tolerance\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'undock_angular_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'max_retries\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'base_frame\\n'\n", + " ':\\n'\n", + " '\"base_link\"\\n'\n", + " 'fixed_frame\\n'\n", + " ':\\n'\n", + " '\"odom\"\\n'\n", + " 'dock_backwards\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'dock_prestaging_tolerance\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# Types of docks\\n'\n", + " 'dock_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'nova_carter_dock'\\n\"\n", + " ']\\n'\n", + " 'nova_carter_dock\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'opennav_docking::SimpleChargingDock'\\n\"\n", + " 'docking_threshold\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'staging_x_offset\\n'\n", + " ':\\n'\n", + " '-0.7\\n'\n", + " 'use_external_detection_pose\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_battery_status\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_stall_detection\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'external_detection_timeout\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'external_detection_translation_x\\n'\n", + " ':\\n'\n", + " '-0.18\\n'\n", + " 'external_detection_translation_y\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'external_detection_rotation_roll\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_pitch\\n'\n", + " ':\\n'\n", + " '-1.57\\n'\n", + " 'external_detection_rotation_yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'filter_coef\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " '# Sep. file of dock instances so config file can be used in '\n", + " 'multiple locations\\n'\n", + " 'dock_database\\n'\n", + " ':\\n'\n", + " '/my/path/to/dock_database.yaml\\n'\n", + " 'controller\\n'\n", + " ':\\n'\n", + " 'k_phi\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'k_delta\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'v_linear_min\\n'\n", + " ':\\n'\n", + " '0.15\\n'\n", + " 'v_linear_max\\n'\n", + " ':\\n'\n", + " '0.15',\n", + " 'context': 'The maximum speed is 15 cm/s to slowly and carefully back into '\n", + " 'the dock and we’ll retry docking 3x in case charging is not '\n", + " 'detected or we lose detected dock tracks during the attempt.',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': 'nova_carter_dock_params_dir\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nova_carter_docking'\\n\"\n", + " '),\\n'\n", + " \"'params'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " 'os\\n'\n", + " '.\\n'\n", + " 'path\\n'\n", + " '.\\n'\n", + " 'join\\n'\n", + " '(\\n'\n", + " 'nova_carter_dock_params_dir\\n'\n", + " ',\\n'\n", + " \"'nova_carter_docking.yaml'\\n\"\n", + " ')\\n'\n", + " 'docking_server\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'opennav_docking'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'docking_server'\\n\"\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'params_file\\n'\n", + " '],\\n'\n", + " ')',\n", + " 'context': 'This server can now be added to your launch file with the path '\n", + " 'to this parameter file for use (or added to your main shared '\n", + " 'configuration file).',\n", + " 'filename': 'use_battery_status',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'use_dock_id\\n'\n", + " 'True\\n'\n", + " '# Whether to use the dock_id or dock_pose fields\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_id\\n'\n", + " '# Dock name or ID to dock at, from given dock database\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'geometry_msgs/PoseStamped\\n'\n", + " 'dock_pose\\n'\n", + " '# Dock pose\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " '# If using dock_pose, what type of dock it is. Not necessary if '\n", + " 'only using one type of dock.\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'float32\\n'\n", + " 'max_staging_time\\n'\n", + " '1000\\n'\n", + " '.0\\n'\n", + " \"# Maximum time for navigation to get to the dock's staging pose.\\n\"\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'navigate_to_staging_pose\\n'\n", + " 'True\\n'\n", + " '# Whether or not to navigate to staging pose or assume robot is '\n", + " 'already at staging pose within tolerance to execute behavior\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'state\\n'\n", + " '# Current docking state\\n'\n", + " '\\n'\n", + " 'builtin_interfaces/Duration\\n'\n", + " 'docking_time\\n'\n", + " '# Docking time elapsed\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'num_retries\\n'\n", + " '0\\n'\n", + " '# Number of retries attempted',\n", + " 'context': 'Optionally, you can disable using Nav2 to navigate to the '\n", + " 'staging pose if outside of the pre-staging tolerance '\n", + " 'usingnavigate_to_staging_pose=Falseor set the maximum time for '\n", + " 'staging navigationmax_staging_time.',\n", + " 'filename': 'max_staging_time',\n", + " 'language': 'unknown'},\n", + " {'code': '#goal definition\\n'\n", + " '\\n'\n", + " 'string\\n'\n", + " 'dock_type\\n'\n", + " 'float32\\n'\n", + " 'max_undocking_time\\n'\n", + " '30\\n'\n", + " '.0\\n'\n", + " '# Maximum time to undock\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#result definition\\n'\n", + " '\\n'\n", + " 'bool\\n'\n", + " 'success\\n'\n", + " 'True\\n'\n", + " '# docking success status\\n'\n", + " '\\n'\n", + " 'uint16\\n'\n", + " 'error_code\\n'\n", + " '0\\n'\n", + " '# Contextual error code, if any\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '---\\n'\n", + " '\\n'\n", + " '#feedback definition',\n", + " 'context': 'TheUndockRobotaction is even simpler. There are no required goal '\n", + " 'fields exceptdock_typeif undocking is being called when the '\n", + " 'server’s instance did not dock the robot to store its current '\n", + " 'state information (such as after a restart on the dock).\\n'\n", + " 'It contains no feedback and returns thesuccessstate and '\n", + " 'theerror_codeif a problem occurs.',\n", + " 'filename': 'error_code',\n", + " 'language': 'unknown'},\n", + " {'code': 'def\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " '\"\"\\n'\n", + " '):\\n'\n", + " '\"\"\"Send a `DockRobot` action request.\"\"\"\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\"Waiting for \\'DockRobot\\' action server\"\\n'\n", + " ')\\n'\n", + " 'while\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'wait_for_server\\n'\n", + " '(\\n'\n", + " 'timeout_sec\\n'\n", + " '=\\n'\n", + " '1.0\\n'\n", + " '):\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " '\\'\"DockRobot\" action server not available, waiting...\\'\\n'\n", + " ')\\n'\n", + " 'goal_msg\\n'\n", + " '=\\n'\n", + " 'DockRobot\\n'\n", + " '.\\n'\n", + " 'Goal\\n'\n", + " '()\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'use_dock_id\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " 'goal_msg\\n'\n", + " '.\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " 'dock_id\\n'\n", + " '# if wanting to use ID instead\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking at ID: '\\n\"\n", + " '+\\n'\n", + " 'str\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'...'\\n\"\n", + " ')\\n'\n", + " 'send_goal_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'docking_client\\n'\n", + " '.\\n'\n", + " 'send_goal_async\\n'\n", + " '(\\n'\n", + " 'goal_msg\\n'\n", + " ',\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " '_feedbackCallback\\n'\n", + " ')\\n'\n", + " 'rclpy\\n'\n", + " '.\\n'\n", + " 'spin_until_future_complete\\n'\n", + " '(\\n'\n", + " 'self\\n'\n", + " ',\\n'\n", + " 'send_goal_future\\n'\n", + " ')\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '=\\n'\n", + " 'send_goal_future\\n'\n", + " '.\\n'\n", + " 'result\\n'\n", + " '()\\n'\n", + " 'if\\n'\n", + " 'not\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'accepted\\n'\n", + " ':\\n'\n", + " 'print\\n'\n", + " '(\\n'\n", + " \"'Docking request was rejected!'\\n\"\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'False\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'result_future\\n'\n", + " '=\\n'\n", + " 'self\\n'\n", + " '.\\n'\n", + " 'goal_handle\\n'\n", + " '.\\n'\n", + " 'get_result_async\\n'\n", + " '()\\n'\n", + " 'return\\n'\n", + " 'True\\n'\n", + " '...\\n'\n", + " 'dock_id\\n'\n", + " '=\\n'\n", + " \"'home_dock'\\n\"\n", + " 'tester\\n'\n", + " '.\\n'\n", + " 'dockRobot\\n'\n", + " '(\\n'\n", + " 'dock_id\\n'\n", + " ')',\n", + " 'context': 'This script demonstrates the essential use of the Docking '\n", + " 'Server.\\n'\n", + " 'However, it does not use the dock database of pre-mapped dock '\n", + " 'locations that you setup.\\n'\n", + " 'After you launch Nav2 and localize your robot in your map, we '\n", + " 'can adjustdockRobot()to take in your desireddock_idand perform '\n", + " 'docking instead:\\n'\n", + " 'Then, we can see the full docking system in action in a '\n", + " 'non-trivial environment!',\n", + " 'filename': 'dock_id',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Model Predictive Path Integral Controller\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## MPPI Parameters\n", + "\n", + "\n", + "## Trajectory Visualization\n", + "\n", + "\n", + "## Path Handler\n", + "\n", + "\n", + "## Ackermann Motion Model\n", + "\n", + "\n", + "## Constraint Critic\n", + "This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints\n", + "\n", + "## Goal Angle Critic\n", + "This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal\n", + "\n", + "## Goal Critic\n", + "This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal\n", + "\n", + "## Obstacles Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles.\n", + "\n", + "## Cost Critic\n", + "This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values.\n", + "\n", + "## Path Align Critic\n", + "This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior.\n", + "\n", + "## Path Angle Critic\n", + "This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors.\n", + "\n", + "## Path Follow Critic\n", + "This critic incentivizes making progress along the path. This is what drives the robot forward along the path.\n", + "\n", + "## Prefer Forward Critic\n", + "This critic incentivizes moving in the forward direction, rather than reversing.\n", + "\n", + "## Twirling Critic\n", + "This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent.\n", + "\n", + "## Velocity Deadband Critic\n", + "This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms.\n", + "\n", + "## Example\n", + "\n", + "\n", + "## Notes to Users\n", + "\n", + "\n", + "## General Words of Wisdom\n", + "Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger.\n", + "Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot.\n", + "The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost.\n", + "Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below:\n", + "\n", + "## Prediction Horizon, Costmap Sizing, and Offsets\n", + "As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width.\n", + "The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker.\n", + "The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline.\n", + "\n", + "## Obstacle, Inflation Layer, and Path Following\n", + "There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.\n", + "Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.\n", + "As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly.\n", + "Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_mppi_controller::MPPIController\"\\n'\n", + " 'time_steps\\n'\n", + " ':\\n'\n", + " '56\\n'\n", + " 'model_dt\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'batch_size\\n'\n", + " ':\\n'\n", + " '2000\\n'\n", + " 'vx_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'vy_std\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'wz_std\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'vx_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'vx_min\\n'\n", + " ':\\n'\n", + " '-0.35\\n'\n", + " 'vy_max\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'wz_max\\n'\n", + " ':\\n'\n", + " '1.9\\n'\n", + " 'ax_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'ax_min\\n'\n", + " ':\\n'\n", + " '-3.0\\n'\n", + " 'ay_max\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'az_max\\n'\n", + " ':\\n'\n", + " '3.5\\n'\n", + " 'iteration_count\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'prune_distance\\n'\n", + " ':\\n'\n", + " '1.7\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'temperature\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " 'gamma\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " 'motion_model\\n'\n", + " ':\\n'\n", + " '\"DiffDrive\"\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'reset_period\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " '# (only in Humble)\\n'\n", + " 'regenerate_noises\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'TrajectoryVisualizer\\n'\n", + " ':\\n'\n", + " 'trajectory_step\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'time_step\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " 'AckermannConstraints\\n'\n", + " ':\\n'\n", + " 'min_turning_r\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'critics\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"ConstraintCritic\"\\n'\n", + " ',\\n'\n", + " '\"CostCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalCritic\"\\n'\n", + " ',\\n'\n", + " '\"GoalAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAlignCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathFollowCritic\"\\n'\n", + " ',\\n'\n", + " '\"PathAngleCritic\"\\n'\n", + " ',\\n'\n", + " '\"PreferForwardCritic\"\\n'\n", + " ']\\n'\n", + " 'ConstraintCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '4.0\\n'\n", + " 'GoalCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'GoalAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'PreferForwardCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " '# ObstaclesCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# repulsion_weight: 1.5\\n'\n", + " '# critical_weight: 20.0\\n'\n", + " '# consider_footprint: false\\n'\n", + " '# collision_cost: 10000.0\\n'\n", + " '# collision_margin_distance: 0.1\\n'\n", + " '# near_goal_distance: 0.5\\n'\n", + " '# inflation_radius: 0.55 # (only in Humble)\\n'\n", + " '# cost_scaling_factor: 10.0 # (only in Humble)\\n'\n", + " 'CostCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '3.81\\n'\n", + " 'critical_cost\\n'\n", + " ':\\n'\n", + " '300.0\\n'\n", + " 'consider_footprint\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'collision_cost\\n'\n", + " ':\\n'\n", + " '1000000.0\\n'\n", + " 'near_goal_distance\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '2\\n'\n", + " 'PathAlignCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '14.0\\n'\n", + " 'max_path_occupancy_ratio\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'trajectory_point_step\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'use_path_orientations\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'PathFollowCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '5\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '1.4\\n'\n", + " 'PathAngleCritic\\n'\n", + " ':\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'cost_power\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'cost_weight\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'offset_from_furthest\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'threshold_to_consider\\n'\n", + " ':\\n'\n", + " '0.5\\n'\n", + " 'max_angle_to_furthest\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'mode\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '# VelocityDeadbandCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# cost_power: 1\\n'\n", + " '# cost_weight: 35.0\\n'\n", + " '# deadband_velocities: [0.05, 0.05, 0.05]\\n'\n", + " '# TwirlingCritic:\\n'\n", + " '# enabled: true\\n'\n", + " '# twirling_cost_power: 1\\n'\n", + " '# twirling_cost_weight: 10.0',\n", + " 'context': 'The array of deadband velocities [vx, vz, wz]. A zero array '\n", + " 'indicates that the critic will take no action.',\n", + " 'filename': 'inflation_radius',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Iron to Jazzy\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## BehaviorTree.CPP upgraded to version 4.5+\n", + "Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly.\n", + "You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are:\n", + "\n", + "## Added TwistStamped Option for Commands\n", + "A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects.\n", + "\n", + "## Add VelocityPolygon in Collision Monitor\n", + "PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection.\n", + "\n", + "## Change polygon points parameter format in Collision Monitor\n", + "PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D.\n", + "Now we can define a polygon’s points in string that has avector>structure like this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of 4 points described. An example of a Square polygon will be written as follows.\n", + "\n", + "## Introduction of Soft-Real Time Action Servers\n", + "PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary.\n", + "The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well!\n", + "\n", + "## opennav_coverageProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system.\n", + "If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here.\n", + "\n", + "## opennav_dockingProject\n", + "A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos.\n", + "This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way.\n", + "It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!)\n", + "SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package!\n", + "\n", + "## Introduce a new Multi-Robot Bringup Launch\n", + "PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments.\n", + "Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files.\n", + "\n", + "## New option for the Voxel and Obstacle Layers\n", + "PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and\n", + "easily prevent the robot to go through places that are not present in the static map.\n", + "\n", + "## use_interpolation RPP Parameter Depreciated\n", + "After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases.\n", + "\n", + "## Changes to MPPI Goal Critic\n", + "The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration.\n", + "\n", + "## Changes to MPPI Path Angle Critic\n", + "MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too.\n", + "mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize.\n", + "mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require.\n", + "\n", + "## Changes to MPPI Path Handling For Directionality\n", + "MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested.\n", + "See MPPI’s configuration guide for complete information.\n", + "\n", + "## Addition of new MPPI Cost Critic\n", + "Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you.\n", + "This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes.\n", + "See the configuration guide for more information.\n", + "\n", + "## MPPI Acceleration\n", + "New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy!\n", + "\n", + "## Move Error Code Enumerations\n", + "PR #3693moves the enumeration codes from the goal to the result section.\n", + "\n", + "## Substitution in parameter file\n", + "Enabled substitution in parameter file. For example, you can write the following\n", + "For more information about substitutions syntax, seehere\n", + "\n", + "## Allow Behavior Server Plugins to Access The Action Result\n", + "PR #3704allows behavior servers plugins to access and modify the action result.\n", + "\n", + "## Smac Planner Debug Param Name Change\n", + "debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well.\n", + "\n", + "## Smac Planner On Approach to Goal Shortcutting Solutions\n", + "PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal.\n", + "It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required.\n", + "This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function.\n", + "\n", + "## Added GPS Waypoint Follower Server\n", + "This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website.\n", + "\n", + "## Smac Planner Hybrid-A* New Features\n", + "New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide.\n", + "\n", + "## New node in nav2_collision_monitor: Collision Detector\n", + "In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector.\n", + "It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision).\n", + "\n", + "## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector\n", + "In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector.\n", + "\n", + "## Expose action server’s result timeout\n", + "In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers.\n", + "This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result\n", + "is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability\n", + "to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes.\n", + "\n", + "## RewrittenYaml could add new parameters to YAMLs\n", + "NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument.\n", + "The change was intoroduced in the scope ofPR #3785fix.\n", + "\n", + "## Simple Commander API Allows Multi-Robot Namespacing\n", + "The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details.\n", + "\n", + "## Change duration type in wait_action node\n", + "In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action.\n", + "\n", + "## The costmap activation fails when required transforms are not available\n", + "In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails,\n", + "if the transformation from the robot base frame to the global frame does not become available during this timeout.\n", + "\n", + "## Subtrees Obtain Shared Resources\n", + "PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc).\n", + "\n", + "## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior\n", + "PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used.\n", + "Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0.\n", + "\n", + "## BtActionServer: use native library haltTree()\n", + "PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree().\n", + "Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt().\n", + "Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption.\n", + "\n", + "## Global Frame Removed from 2 BT Nodes\n", + "The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation.\n", + "\n", + "## Introduction ofCostmapUpdate.msg\n", + "PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior.\n", + "To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse.\n", + "To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass.\n", + "\n", + "## Full Stack Uses Node Clocks\n", + "The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock.\n", + "\n", + "## New Graceful Motion Controller\n", + "PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory.\n", + "SeeGraceful Controllerfor more information.\n", + "\n", + "## Plugin Libraries in BT Navigator Only Includes Custom Nodes\n", + "New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load.\n", + "\n", + "## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers\n", + "In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly.\n", + "The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application.\n", + "In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes.\n", + "Here we can see the working demo of the plugin:\n", + "In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized.\n", + "In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF.\n", + "\n", + "## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing\n", + "In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same.\n", + "Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true.\n", + "Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward.\n", + "\n", + "## Cancel Checker Interface For GlobalPlanner\n", + "PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task.\n", + "Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled.\n", + "New interface forGlobalPlanner::createPlan:\n", + "This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()).\n", + "Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations.\n", + "\n", + "## New BtActionServer/BtNavigator parameter\n", + "PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description.\n", + "\n", + "## New collision monitor parameter\n", + "PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription.\n", + "\n", + "## New graceful cancellation API for Controllers\n", + "PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits.\n", + "\n", + "## Standardization of Plugin Naming with Double Colons (::)\n", + "`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include:\n", + "\n", + "## Collision monitor: dynamic radius for circle type polygons\n", + "PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic.\n", + "\n", + "## Static Layer: new parameterfootprint_clearing_enabled\n", + "PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior.\n", + "\n", + "## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism)\n", + "PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0.\n", + "\n", + "## Rotation Shim Controller: new parameterrotate_to_goal_heading\n", + "PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others.\n", + "\n", + "## MPPI Controller: Addition of acceleration constraints\n", + "PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints.\n", + "\n", + "## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration\n", + "PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'PolygonFront\\n'\n", + " ':\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '\"polygon\"\\n'\n", + " 'points\\n'\n", + " ':\\n'\n", + " '\"[[0.3,\\n'\n", + " '0.3],\\n'\n", + " '[0.3,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '-0.3],\\n'\n", + " '[0.0,\\n'\n", + " '0.3]]\"\\n'\n", + " 'action_type\\n'\n", + " ':\\n'\n", + " '\"none\"\\n'\n", + " 'min_points\\n'\n", + " ':\\n'\n", + " '4\\n'\n", + " 'visualize\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'polygon_pub_topic\\n'\n", + " ':\\n'\n", + " '\"polygon_front\"',\n", + " 'context': 'PR #4020changes the format of the Polygon points parameter '\n", + " 'fromvectortostring. This makes the polygon description '\n", + " 'more uniform across the Collision Monitor and Costmap_2D.\\n'\n", + " 'Now we can define a polygon’s points in string that has '\n", + " 'avector>structure like '\n", + " 'this\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"with a minimum of '\n", + " '4 points described. An example of a Square polygon will be '\n", + " 'written as follows.',\n", + " 'filename': '\"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]\"',\n", + " 'language': 'unknown'},\n", + " {'code': ' soft rtprio 99\\n hard rtprio 99\\n',\n", + " 'context': 'PR #3914adds soft real-time prioritization to the controller '\n", + " 'server to better ensure resources to time sensitive portions of '\n", + " 'the codebase. The Simple Action Server now has arealtimeinput '\n", + " 'field exposed in the Controller Server via the '\n", + " 'parameteruse_realtime_prioritywhich will set the controller’s '\n", + " 'execution thread to a higher priority than the rest of the '\n", + " 'system to meet scheduling deadlines. To use this feature, you '\n", + " 'use set the following inside of/etc/security/limits.confto give '\n", + " 'userspace access to elevated prioritization permissions. This is '\n", + " 'currently only enabled in the Controller Server, who’s execution '\n", + " 'thread is sensitive to scheduling priorities, but could be set '\n", + " 'with other threads in the future if found necessary.',\n", + " 'filename': '/etc/security/limits.conf',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'default_nav_to_pose_bt_xml\\n'\n", + " ':\\n'\n", + " '$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml',\n", + " 'context': 'Enabled substitution in parameter file. For example, you can '\n", + " 'write the following',\n", + " 'filename': 'ObstaclesCritic',\n", + " 'language': 'unknown'},\n", + " {'code': 'virtual\\n'\n", + " 'nav_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'Path\\n'\n", + " 'createPlan\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'start\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'geometry_msgs\\n'\n", + " '::\\n'\n", + " 'msg\\n'\n", + " '::\\n'\n", + " 'PoseStamped\\n'\n", + " '&\\n'\n", + " 'goal\\n'\n", + " ',\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'function\\n'\n", + " '<\\n'\n", + " 'bool\\n'\n", + " '()\\n'\n", + " '>\\n'\n", + " 'cancel_checker\\n'\n", + " ')',\n", + " 'context': 'PR #4148introduces a new interface for theGlobalPlannerto allow '\n", + " 'for the cancellation of the current planning task.\\n'\n", + " 'Before the planners would continue to plan even if the goal was '\n", + " 'cancelled, now they can check it and stop planning if the goal '\n", + " 'is cancelled.\\n'\n", + " 'New interface forGlobalPlanner::createPlan:',\n", + " 'filename': 'GlobalPlanner::createPlan',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Concepts\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## ROS 2\n", + "ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing.\n", + "\n", + "## Action Server\n", + "Just as in ROS, action servers are a common way to control long running tasks like navigation.\n", + "This stack makes more extensive use of actions, and in some cases, without an easy topic interface.\n", + "It is more important to understand action servers as a developer in ROS 2.\n", + "Some simple CLI examples can be found in theROS 2 documentation.\n", + "Action servers are similar to a canonical service server.\n", + "A client will request some task to be completed, except, this task may take a long time.\n", + "An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right.\n", + "In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result.\n", + "It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread.\n", + "Since it is long-running, action servers will also provide feedback to their clients.\n", + "This feedback can be anything and is defined in the ROS.actionalong with the request and result types.\n", + "In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle.\n", + "In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success.\n", + "Feedback and results can be gathered synchronously by registering callbacks with the action client.\n", + "They may also be gathered by asynchronously requesting information from the shared future objects.\n", + "Both require spinning the client node to process callback groups.\n", + "Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message.\n", + "They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries.\n", + "Each will have their own unique.actiontype innav2_msgsfor interacting with the servers.\n", + "\n", + "## Lifecycle Nodes and Bond\n", + "Lifecycle (or Managed, more correctly) nodes are unique to ROS 2.\n", + "More information can befound here.\n", + "They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers.\n", + "This helps in deterministic behavior of ROS systems in startup and shutdown.\n", + "It also helps users structure their programs in reasonable ways for commercial uses and debugging.\n", + "When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading.\n", + "By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring.\n", + "After, it is possible to activate the node by transitioning through the activating stage.\n", + "This state will allow the node to process information and be fully setup to run.\n", + "The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory.\n", + "The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information.\n", + "To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state.\n", + "The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively.\n", + "The lifecycle node framework is used extensively through out this project and all servers utilize it.\n", + "It is best convention for all ROS systems to use lifecycle nodes if it is possible.\n", + "Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode.\n", + "This wrapper wraps much of the complexities of LifecycleNodes for typical applications.\n", + "It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active.\n", + "If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details.\n", + "\n", + "## Behavior Trees\n", + "Behavior trees (BT) are becoming increasingly common in complex robotics tasks.\n", + "They are a tree structure of tasks to be completed.\n", + "It creates a more scalable and human-understandable framework for defining multi-step or many state applications.\n", + "This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions.\n", + "An example would be a soccer-playing robot.\n", + "Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules.\n", + "Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear.\n", + "With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors.\n", + "More information can be foundin this book.\n", + "Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow.\n", + "It should only take about 30 minutes.\n", + "Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis.\n", + "For this project, we useBehaviorTree CPP V4as the behavior tree library.\n", + "We create node plugins which can be constructed into a tree, inside theBTNavigator.\n", + "The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated.\n", + "At this point, we can march through the behavior tree to navigate.\n", + "One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin.\n", + "An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task.\n", + "Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface.\n", + "Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM).\n", + "Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand.\n", + "However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution.\n", + "\n", + "## Navigation Servers\n", + "Planners and controllers are at the heart of a navigation task.\n", + "Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant.\n", + "Smoothers can be used for additional quality improvements of the planned path.\n", + "In this section, the general concepts around them and their uses in this project are analyzed.\n", + "\n", + "## Planner, Controller, Smoother and Recovery Servers\n", + "Four of the action servers in this project are the planner, behavior, smoother and controller servers.\n", + "These action servers are used to host a map of algorithm plugins to complete various tasks.\n", + "They also host the environmental representation used by the algorithm plugins to compute their outputs.\n", + "The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use.\n", + "These types are the pluginlib names that have been registered and the names are the aliases for the task.\n", + "An example would be the DWB controller used with nameFollowPath, as it follows a reference path.\n", + "In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath..\n", + "These three servers then expose an action interface corresponding to their task.\n", + "When the behavior tree ticks the corresponding BT node, it will call the action server to process its task.\n", + "The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm.\n", + "This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms.\n", + "For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool.\n", + "Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate.\n", + "For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server.\n", + "This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share.\n", + "The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks.\n", + "We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate.\n", + "Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types.\n", + "It is advisable to use the provided servers if possible at all times.\n", + "If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework.\n", + "The new server should use the new type and plugin interface, similar to the provided servers.\n", + "A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins.\n", + "If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces.\n", + "\n", + "## Planners\n", + "The task of a planner is to compute a path to complete some objective function.\n", + "The path can also be known as a route, depending on the nomenclature and algorithm selected.\n", + "Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space).\n", + "The planner will have access to a global environmental representation and sensor data buffered into it.\n", + "Planners can be written to:\n", + "The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose.\n", + "However, many classes of plans and routes exist which are supported.\n", + "\n", + "## Controllers\n", + "Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task.\n", + "The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow.\n", + "Many controller will project the robot forward in space and compute a locally feasible path at each update iteration.\n", + "Controllers can be written to:\n", + "The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan.\n", + "However, many classes of controllers and local planners exist.\n", + "It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks.\n", + "\n", + "## Behaviors\n", + "Recovery behaviors are a mainstay of fault-tolerant systems.\n", + "The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them.\n", + "Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles.\n", + "The clear costmap recovery would then be triggered to allow the robot to move.\n", + "Another example would be if the robot was stuck due to dynamic obstacles or poor control.\n", + "Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully.\n", + "Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help.\n", + "This can be done via email, SMS, Slack, Matrix, etc.\n", + "It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API.\n", + "\n", + "## Smoothers\n", + "As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial.\n", + "Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations,\n", + "but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation.\n", + "Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path.\n", + "The general task in Nav2 for a smoother is to receive a path and return its improved version.\n", + "However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server.\n", + "\n", + "## Robot Footprints\n", + "It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Waypoint Following\n", + "Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations.\n", + "Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors.\n", + "This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input.\n", + "It is a nice demo application for how to use Nav2 in a sample application.\n", + "However, it could be used for more than just a sample application.\n", + "There are 2 schools of thoughts for fleet managers / dispatchers:\n", + "In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application.\n", + "In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy.\n", + "Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case.\n", + "nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources.\n", + "There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints.\n", + "\n", + "## State Estimation\n", + "Within the navigation project, there are 2 major transformations that need to be provided, according to community standards.\n", + "Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system.\n", + "\n", + "## Standards\n", + "REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem.\n", + "These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community.\n", + "In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot.\n", + "TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations.\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "It is then the role of the odometry system to provide theodom->base_linktransformation.\n", + "The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF.\n", + "\n", + "## Global Positioning: Localization and SLAM\n", + "It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation.\n", + "We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map.\n", + "We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map.\n", + "These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid.\n", + "Multiple positioning methods can be fused together using robot localization, discussed more below.\n", + "\n", + "## Odometry\n", + "It is the role of the odometry system to provide theodom->base_linktransformation.\n", + "Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs.\n", + "The goal of the odometry is to provide a smooth and continuous local frame based on robot motion.\n", + "The global positioning system will update the transformation relative to the global frame to account for the odometric drift.\n", + "Robot Localizationis typically used for this fusion.\n", + "It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic.\n", + "A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner.\n", + "The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates.\n", + "\n", + "## Environmental Representation\n", + "The environmental representation is the way the robot perceives its environment.\n", + "It also acts as the central localization for various algorithms and data sources to combine their information into a single space.\n", + "This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently.\n", + "\n", + "## Costmaps and Layers\n", + "The current environmental representation is a costmap.\n", + "A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost.\n", + "This costmap is then searched to compute a global plan or sampled to compute local control efforts.\n", + "Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap.\n", + "This includes information from LIDAR, RADAR, sonar, depth images, etc.\n", + "It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer.\n", + "Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors.\n", + "Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic.\n", + "Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking.\n", + "\n", + "## Costmap Filters\n", + "Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes.\n", + "Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack.\n", + "Costmap filters are implemented as costmap plugins.\n", + "These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks.\n", + "In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask.\n", + "This data is being linearly transformed into a feature map in a filter space.\n", + "Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is.\n", + "For example, the following functionality could be made by use of costmap filters:\n", + "\n", + "## Other Forms\n", + "Various other forms of environmental representations exist.\n", + "These include:\n", + "\n", + "## Nav2 Academic Overview\n", + "\n", + "\n", + "=== Document ===\n", + "Title: GoalUpdated\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Vector of goals to check. Takes in a blackboard variable, '\n", + " '“{goals}” if not specified.',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Jazzy to K-Turtle\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## TwistStamped Default CmdVel Change\n", + "In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications.\n", + "it also allows for rejection of stale velocity messages, which can be useful in some applications.\n", + "Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately.\n", + "The topic names are the same.\n", + "However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications.\n", + "See the configuration guide for more information on how to configure this parameter for each node.\n", + "An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4.\n", + "\n", + "## New Nav2 Loopback Simulator\n", + "Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc).\n", + "It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations.\n", + "\n", + "## Docking with Static Infrastructure or Dynamic Docking\n", + "InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server.\n", + "This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet.\n", + "It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock.\n", + "\n", + "## New RViz panel for Docking\n", + "InPR #4458a new RViz panel was added to interact with the Docking Server.\n", + "This panel allows the user to:\n", + "The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action.\n", + "Here we can see the working demo of the plugin:\n", + "\n", + "## New BT Nodes\n", + "Below is a list of new BT Nodes added:\n", + "\n", + "## New RViz Tool for Costmap Cost Cell Inspection\n", + "InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose.\n", + "Usage:\n", + "Working demo of the tool:\n", + "\n", + "## Fix flickering visualization\n", + "InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues.\n", + "Default Value:\n", + "Minimum Value Without Flickering:\n", + "Before:\n", + "After:\n", + "\n", + "## Option to limit velocity through DWB trajectory\n", + "InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity.\n", + "Default value:\n", + "\n", + "## Option to disable zero velocity publishing on goal exit\n", + "InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit.\n", + "Default value:\n", + "\n", + "## Added optional collision checking for the Docking Server\n", + "InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock.\n", + "Default value:\n", + "\n", + "## Revamped multirobot bringup and config files to use namespaces\n", + "InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically:\n", + "Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name.\n", + "If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior.\n", + "For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace:\n", + "\n", + "## Removed global map_topic from Costmap node\n", + "InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example:\n", + "\n", + "## Simplified Costmap2DROS constructors\n", + "The following constructors forCostmap2DROShave been removed:\n", + "They have been consolidated into a single one:\n", + "Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did).\n", + "Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '...\\n'\n", + " ']\\n'\n", + " '# Not supported anymore\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '# Do this instead\\n'\n", + " 'map_topic\\n'\n", + " ':\\n'\n", + " 'my_map',\n", + " 'context': 'InPR #4715the globalmap_topicparameter has been removed from '\n", + " 'theCostmap2DROSnode. This parameterwas only used in '\n", + " 'theStaticLayerand should be defined as a parameter local to '\n", + " 'theStaticLayerinstead, for example:',\n", + " 'filename': 'StaticLayer',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'local_namespace\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " ');\\n'\n", + " 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'The following constructors forCostmap2DROShave been removed:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'},\n", + " {'code': 'explicit\\n'\n", + " 'Costmap2DROS\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'parent_namespace\\n'\n", + " '=\\n'\n", + " '\"/\"\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'bool\\n'\n", + " '&\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'false\\n'\n", + " ');',\n", + " 'context': 'They have been consolidated into a single one:',\n", + " 'filename': 'Costmap2DROS',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Humble to Iron\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## New Behavior-Tree Navigator Plugins\n", + "New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition.\n", + "SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins.\n", + "\n", + "## Added Collision Monitor\n", + "PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup.\n", + "\n", + "## Removed use_sim_time from yaml\n", + "PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument.\n", + "\n", + "## Run-time Speed up of Smac Planner\n", + "The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings.\n", + "\n", + "## Recursive Refinement of Smac and Simple Smoothers\n", + "The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4.\n", + "\n", + "## Simple Commander Python API\n", + "PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details.\n", + "\n", + "## Smac Planner Start Pose Included in Path\n", + "PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing.\n", + "\n", + "## Parameterizable Collision Checking in RPP\n", + "PR 3204adds makes collision checking for RPP optional (default on).\n", + "\n", + "## Expanded Planner Benchmark Tests\n", + "PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation.\n", + "\n", + "## Smac Planner Path Tolerances\n", + "PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose.\n", + "\n", + "## costmap_2d_node default constructor\n", + "PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file.\n", + "\n", + "## Feedback for Navigation Failures\n", + "PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found.\n", + "PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given.\n", + "PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control.\n", + "PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure.\n", + "A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare.\n", + "The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures.\n", + "The error codes produced from the servers follow the guidelines stated below.\n", + "Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers.\n", + "Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN.\n", + "The current implemented servers with error codes are:\n", + "This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application.\n", + "The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed.\n", + "SeeAdding a New Nav2 Task Serverand the PR for additional information.\n", + "\n", + "## Costmap Filters\n", + "Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229).\n", + "Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228).\n", + "\n", + "## Savitzky-Golay Smoother\n", + "Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details.\n", + "\n", + "## Changes to Map yaml file path for map_server node in Launch\n", + "PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml.\n", + "\n", + "## SmootherSelector BT Node\n", + "PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details.\n", + "\n", + "## Publish Costmap Layers\n", + "PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer.\n", + "\n", + "## Give Behavior Server Access to Both Costmaps\n", + "PR #3255adds the ability for a behavior to access the local and global costmap.\n", + "To update behaviors, any reference to the global_frame must be updated to the local_frame parameter\n", + "along with theconfigurationmethod which now takes in the local and global collision checkers.\n", + "Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint)\n", + "orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources.\n", + "\n", + "## New Model Predictive Path Integral Controller\n", + "The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes.\n", + "See the README.md andModel Predictive Path Integral Controllerpage for more detail.\n", + "\n", + "## Behavior Tree Uses Error Codes\n", + "PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them.\n", + "TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against.\n", + "TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a controller recovery.\n", + "TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a planner recovery.\n", + "TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION.\n", + "If the error code is a match, the condition returnsSUCCESS.\n", + "These error code are potentially able to be cleared by a smoother recovery.\n", + "\n", + "## Load, Save and Loop Waypoints from the Nav2 Panel in RViz\n", + "PR #3165provides three new functionalities for the nav2 panel in RViz, they are:\n", + "Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server.\n", + "\n", + "## DWB Forward vs Reverse Pruning\n", + "PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening.\n", + "\n", + "## More stable regulation on curves for long lookahead distances\n", + "PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist.\n", + "\n", + "## Publish Collision Monitor State\n", + "PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name.\n", + "\n", + "## Renamed ROS-parameter in Collision Monitor\n", + "PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1.\n", + "\n", + "## New safety behavior model “limit” in Collision Monitor\n", + "PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape.\n", + "\n", + "## Velocity smoother applies deceleration when timeout\n", + "PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout.\n", + "\n", + "## PoseProgressChecker plugin\n", + "PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance.\n", + "\n", + "## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type\n", + "PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction.\n", + "Beware that it is a breaking change and that configuration files will need to be updated.\n", + "\n", + "## IsBatteryChargingCondition BT Node\n", + "PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details.\n", + "\n", + "## Behavior Server Error Codes\n", + "PR #3569updates the behavior server plugins to provide error codes on failure.\n", + "\n", + "## New Denoise Costmap Layer Plugin\n", + "PR #2567adds the new plugin for filtering noise on the costmap.\n", + "Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map.\n", + "The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap.\n", + "More information aboutDenoiseLayerplugin and how it works could be foundhere.\n", + "\n", + "## SmacPlannerHybrid viz_expansions parameter\n", + "PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose.\n", + "\n", + "=== Document ===\n", + "Title: CancelWait\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Input Ports\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'Server timeout (ms).',\n", + " 'filename': 'wait',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Get Backtrace in ROS 2 / Nav2\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This document explains one set of methods for getting backtraces for ROS 2 and Nav2.\n", + "There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience.\n", + "The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem.\n", + "This tutorial applies to both simulated and physical robots.\n", + "This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes.\n", + "By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2.\n", + "\n", + "## Preliminaries\n", + "GDB is the most popular debugger for C++ on Unix systems.\n", + "It can be used to determine the reason for a crash and track threads.\n", + "It may also be used to add breakpoints in your code to check values in memory a particular points in your software.\n", + "Using GDB is a critical skill for all software developers working on C/C++.\n", + "Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose.\n", + "Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them.\n", + "Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset.\n", + "Using GDB luckily is fairly simple after you have the basics under your belt.\n", + "The first step is to add-gto your compiler flags for the ROS package you want to profile / debug.\n", + "This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why.\n", + "If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures.\n", + "Be sure to remove this flag after debugging, it will slow down performance at run-time.\n", + "Adding the following line to yourCMakeLists.txtfor your project should do the trick.\n", + "If your project already has aadd_compile_options(), you can simply add-gto it.\n", + "Then simply rebuild your workspace with this packagecolconbuild--packages-select.\n", + "It may take a little longer than usual to compile.\n", + "Now you’re ready to debug your code!\n", + "If this was a non-ROS project, at this point you might do something like below.\n", + "Here we’re launching a GDB session and telling our program to immediately run.\n", + "Once your program crashes, it will return a gdb session prompt denoted by(gdb).\n", + "At this prompt you can access the information you’re interested in.\n", + "However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem.\n", + "Below are sections to describe the 3 major situations you could run into with ROS 2-based systems.\n", + "Read the section that best describes the problem you’re attempting to solve.\n", + "\n", + "## From a Node\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node.\n", + "While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us.\n", + "--prefixwill execute some bits of code before ourros2command allowing us to insert some information.\n", + "If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command.\n", + "If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons.\n", + "Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix.\n", + "This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details.\n", + "Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments.\n", + "You should now have your node running and should be chugging along with some debug printing.\n", + "Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "For example:\n", + "In this example you should read this in the following way, starting at the bottom:\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From a Launch File\n", + "Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file.\n", + "While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file.\n", + "In your launch file, find the node that you’re interested in debugging.\n", + "For this section, we assume that your launch file contains only a single node (and potentially other information as well).\n", + "TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments.\n", + "We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB.\n", + "We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?).\n", + "Seethis ticketfor more information.\n", + "See below for an example debugging SLAM Toolbox.\n", + "Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined.\n", + "Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Large Project\n", + "Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal.\n", + "For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately.\n", + "These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s).\n", + "As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others.\n", + "If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following:\n", + "Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others:\n", + "Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## From Nav2 Bringup\n", + "To debug directly from the nav2 bringup launch files you may want to do the following:\n", + "Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace.\n", + "In this session, typebacktraceand it will provide you with a backtrace.\n", + "Copy this for your needs.\n", + "See the example trace in the section above for an example.\n", + "These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on.\n", + "Then you can deduce why it crashed.\n", + "When you are done with GDB, typequitand it will exit the session and kill any processes still up.\n", + "It may ask you if you want to kill some threads at the end, say yes.\n", + "\n", + "## Automatic backtrace on crash\n", + "Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration.\n", + "Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'add_compile_options\\n(\\n-g\\n)',\n", + " 'context': 'Adding the following line to yourCMakeLists.txtfor your project '\n", + " 'should do the trick.\\n'\n", + " 'If your project already has aadd_compile_options(), you can '\n", + " 'simply add-gto it.\\n'\n", + " 'Then simply rebuild your workspace with this '\n", + " 'packagecolconbuild--packages-select.\\n'\n", + " 'It may take a little longer than usual to compile.',\n", + " 'filename': 'colconbuild--packages-select',\n", + " 'language': 'unknown'},\n", + " {'code': 'gdb\\nex\\nrun\\n--args\\n/path/to/exe/program\\n',\n", + " 'context': 'Now you’re ready to debug your code!\\n'\n", + " 'If this was a non-ROS project, at this point you might do '\n", + " 'something like below.\\n'\n", + " 'Here we’re launching a GDB session and telling our program to '\n", + " 'immediately run.\\n'\n", + " 'Once your program crashes, it will return a gdb session prompt '\n", + " 'denoted by(gdb).\\n'\n", + " 'At this prompt you can access the information you’re interested '\n", + " 'in.\\n'\n", + " 'However, since this is a ROS project with lots of node '\n", + " 'configurations and other things going on, this isn’t a great '\n", + " 'option for beginners or those that don’t like tons of '\n", + " 'commandline work and understanding the filesystem.',\n", + " 'filename': '(gdb)',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " '--prefix\\n'\n", + " \"'gdb -ex run --args'\\n\"\n", + " '\\n'\n", + " '\\n'\n", + " '--all-other-launch\\n'\n", + " 'arguments\\n',\n", + " 'context': 'Rather than having to revert to finding the install path of the '\n", + " 'executable and typing it all out, we can instead use--prefix.\\n'\n", + " 'This allows us to use the sameros2runsyntax you’re used to '\n", + " 'without having to worry about some of the GDB details.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below. At '\n", + " 'this point you can now get a backtrace.',\n", + " 'filename': 'ros2run',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\n'\n", + " 'gdb\\n'\n", + " ')\\n'\n", + " 'backtrace\\n'\n", + " '\\n'\n", + " '#0 __GI_raise (sig=sig@entry=6) at '\n", + " '../sysdeps/unix/sysv/linux/raise.c:50\\n'\n", + " '#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79\\n'\n", + " '#2 0x00007ffff7c52951 in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#3 0x00007ffff7c5e47c in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#4 0x00007ffff7c5e4e7 in std::terminate() () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#5 0x00007ffff7c5e799 in __cxa_throw () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#6 0x00007ffff7c553eb in ?? () from '\n", + " '/usr/lib/x86_64-linux-gnu/libstdc++.so.6\\n'\n", + " '#7 0x000055555555936c in std::vector '\n", + " '>::_M_range_check (\\n'\n", + " 'this\\n'\n", + " '=\\n'\n", + " '0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1070\\n'\n", + " '\\n'\n", + " '#8 0x0000555555558e1d in std::vector '\n", + " '>::at (this=0x5555555cfdb0,\\n'\n", + " '__n\\n'\n", + " '=\\n'\n", + " '100\\n'\n", + " ')\\n'\n", + " 'at\\n'\n", + " '/usr/include/c++/9/bits/stl_vector.h:1091\\n'\n", + " '\\n'\n", + " '#9 0x000055555555828b in GDBTester::VectorCrash '\n", + " '(this=0x5555555cfb40)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44\\n'\n", + " '\\n'\n", + " '#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108)\\n'\n", + " 'at\\n'\n", + " '/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25\\n',\n", + " 'context': 'In this session, typebacktraceand it will provide you with a '\n", + " 'backtrace.\\n'\n", + " 'Copy this for your needs.\\n'\n", + " 'For example:',\n", + " 'filename': 'backtrace',\n", + " 'language': 'unknown'},\n", + " {'code': 'start_sync_slam_toolbox_node\\n'\n", + " '=\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " '\"slam_toolbox\"\\n'\n", + " ')\\n'\n", + " '+\\n'\n", + " \"'/config/mapper_params_online_sync.yaml'\\n\"\n", + " ',\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '}\\n'\n", + " '],\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'sync_slam_toolbox_node'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'slam_toolbox'\\n\"\n", + " ',\\n'\n", + " 'prefix\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'xterm -e gdb -ex run --args'\\n\"\n", + " '],\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')',\n", + " 'context': 'In your launch file, find the node that you’re interested in '\n", + " 'debugging.\\n'\n", + " 'For this section, we assume that your launch file contains only '\n", + " 'a single node (and potentially other information as well).\\n'\n", + " 'TheNodefunction used in thelaunch_rospackage will take in a '\n", + " 'fieldprefixtaking a list of prefix arguments.\\n'\n", + " 'We will insert the GDB snippet here with one change from our '\n", + " 'node example, use ofxterm.xtermwill pop up a new terminal window '\n", + " 'to show and interact with GDB.\\n'\n", + " 'We do this because of issues handlingstdinon launch files (e.g. '\n", + " 'if you hit control+C, are you talking to GDB or launch?).\\n'\n", + " 'Seethis ticketfor more information.\\n'\n", + " 'See below for an example debugging SLAM Toolbox.',\n", + " 'filename': 'stdin',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below, now in '\n", + " 'thextermsession. At this point you can now get a backtrace.',\n", + " 'filename': 'xterm',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'specific server’s terminal. At this point you can now get a '\n", + " 'backtrace.',\n", + " 'filename': '--ros-args-r__node:=--params-file/absolute/path/to/params.yaml',\n", + " 'language': 'unknown'},\n", + " {'code': '(\\ngdb\\n)',\n", + " 'context': 'Once your server crashes, you’ll see a prompt like below in the '\n", + " 'xterm window. At this point you can now get a backtrace.',\n", + " 'filename': 'ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating with Keepout Zones\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document.\n", + "\n", + "## Requirements\n", + "It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1. Prepare filter mask\n", + "As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask:\n", + "Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile.\n", + "Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness.\n", + "In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool:\n", + "The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles:\n", + "wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields.\n", + "For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area).\n", + "Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used.\n", + "For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones:\n", + "After all keepout areas will be filled save thekeepout_mask.pgmimage.\n", + "Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask:\n", + "Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use.\n", + "\n", + "## 2. Configure Costmap Filter Info Publisher Server\n", + "Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask.\n", + "In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows:\n", + "where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below:\n", + "Note, that:\n", + "Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows:\n", + "\n", + "## 3. Enable Keepout Filter\n", + "Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined:\n", + "Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage.\n", + "It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy.\n", + "To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration:\n", + "\n", + "## 4. Run Nav2 stack\n", + "After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started:\n", + "And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask):\n", + "\n", + "Code Blocks:\n", + "[{'code': 'image: turtlebot3_world.pgm\\n->\\nimage: keepout_mask.pgm\\n',\n", + " 'context': 'Like all other maps, filter mask should have its own YAML '\n", + " 'metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. '\n", + " 'Openkeepout_mask.yamland correctimagefield to a newly made PGM '\n", + " 'mask:',\n", + " 'filename': 'image',\n", + " 'language': 'unknown'},\n", + " {'code': 'import\\n'\n", + " 'os\\n'\n", + " 'from\\n'\n", + " 'ament_index_python.packages\\n'\n", + " 'import\\n'\n", + " 'get_package_share_directory\\n'\n", + " 'from\\n'\n", + " 'launch\\n'\n", + " 'import\\n'\n", + " 'LaunchDescription\\n'\n", + " 'from\\n'\n", + " 'launch.actions\\n'\n", + " 'import\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " ',\\n'\n", + " 'GroupAction\\n'\n", + " 'from\\n'\n", + " 'launch.conditions\\n'\n", + " 'import\\n'\n", + " 'IfCondition\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'LaunchConfiguration\\n'\n", + " ',\\n'\n", + " 'PythonExpression\\n'\n", + " 'from\\n'\n", + " 'launch.substitutions\\n'\n", + " 'import\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'Node\\n'\n", + " ',\\n'\n", + " 'LoadComposableNodes\\n'\n", + " 'from\\n'\n", + " 'launch_ros.actions\\n'\n", + " 'import\\n'\n", + " 'PushRosNamespace\\n'\n", + " 'from\\n'\n", + " 'launch_ros.descriptions\\n'\n", + " 'import\\n'\n", + " 'ComposableNode\\n'\n", + " 'from\\n'\n", + " 'nav2_common.launch\\n'\n", + " 'import\\n'\n", + " 'RewrittenYaml\\n'\n", + " 'def\\n'\n", + " 'generate_launch_description\\n'\n", + " '():\\n'\n", + " '# Get the launch directory\\n'\n", + " 'costmap_filters_demo_dir\\n'\n", + " '=\\n'\n", + " 'get_package_share_directory\\n'\n", + " '(\\n'\n", + " \"'nav2_costmap_filters_demo'\\n\"\n", + " ')\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ']\\n'\n", + " '# Parameters\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ')\\n'\n", + " 'use_sim_time\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ')\\n'\n", + " 'autostart\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ')\\n'\n", + " 'params_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ')\\n'\n", + " 'mask_yaml_file\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ')\\n'\n", + " 'use_composition\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ')\\n'\n", + " 'container_name\\n'\n", + " '=\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ')\\n'\n", + " 'container_name_full\\n'\n", + " '=\\n'\n", + " '(\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " \"'/'\\n\"\n", + " ',\\n'\n", + " 'container_name\\n'\n", + " ')\\n'\n", + " '# Declare the launch arguments\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"''\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Top-level namespace'\\n\"\n", + " ')\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use simulation (Gazebo) clock if true'\\n\"\n", + " ')\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'autostart'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'true'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Automatically startup the nav2 stack'\\n\"\n", + " ')\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'params_file'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to the ROS2 parameters file to use'\\n\"\n", + " ')\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'mask'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Full path to filter mask yaml file to load'\\n\"\n", + " ')\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'use_composition'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'True'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'Use composed bringup if True'\\n\"\n", + " ')\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " '=\\n'\n", + " 'DeclareLaunchArgument\\n'\n", + " '(\\n'\n", + " \"'container_name'\\n\"\n", + " ',\\n'\n", + " 'default_value\\n'\n", + " '=\\n'\n", + " \"'nav2_container'\\n\"\n", + " ',\\n'\n", + " 'description\\n'\n", + " '=\\n'\n", + " \"'The name of container that nodes will load in if use composition'\\n\"\n", + " ')\\n'\n", + " '# Make re-written yaml\\n'\n", + " 'param_substitutions\\n'\n", + " '=\\n'\n", + " '{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ',\\n'\n", + " \"'yaml_filename'\\n\"\n", + " ':\\n'\n", + " 'mask_yaml_file\\n'\n", + " '}\\n'\n", + " 'configured_params\\n'\n", + " '=\\n'\n", + " 'RewrittenYaml\\n'\n", + " '(\\n'\n", + " 'source_file\\n'\n", + " '=\\n'\n", + " 'params_file\\n'\n", + " ',\\n'\n", + " 'root_key\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'param_rewrites\\n'\n", + " '=\\n'\n", + " 'param_substitutions\\n'\n", + " ',\\n'\n", + " 'convert_types\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ')\\n'\n", + " 'load_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'PythonExpression\\n'\n", + " '([\\n'\n", + " \"'not '\\n\"\n", + " ',\\n'\n", + " 'use_composition\\n'\n", + " '])),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'map_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'Node\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'executable\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ',\\n'\n", + " 'emulate_tty\\n'\n", + " '=\\n'\n", + " 'True\\n'\n", + " ',\\n'\n", + " '# https://github.com/ros2/launch/issues/188\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}])\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'load_composable_nodes\\n'\n", + " '=\\n'\n", + " 'GroupAction\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'use_composition\\n'\n", + " '),\\n'\n", + " 'actions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'PushRosNamespace\\n'\n", + " '(\\n'\n", + " 'condition\\n'\n", + " '=\\n'\n", + " 'IfCondition\\n'\n", + " '(\\n'\n", + " 'NotEqualsSubstitution\\n'\n", + " '(\\n'\n", + " 'LaunchConfiguration\\n'\n", + " '(\\n'\n", + " \"'namespace'\\n\"\n", + " '),\\n'\n", + " \"''\\n\"\n", + " ')),\\n'\n", + " 'namespace\\n'\n", + " '=\\n'\n", + " 'namespace\\n'\n", + " '),\\n'\n", + " 'LoadComposableNodes\\n'\n", + " '(\\n'\n", + " 'target_container\\n'\n", + " '=\\n'\n", + " 'container_name_full\\n'\n", + " ',\\n'\n", + " 'composable_node_descriptions\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::MapServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'filter_mask_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_map_server::CostmapFilterInfoServer'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'costmap_filter_info_server'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[\\n'\n", + " 'configured_params\\n'\n", + " ']),\\n'\n", + " 'ComposableNode\\n'\n", + " '(\\n'\n", + " 'package\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager'\\n\"\n", + " ',\\n'\n", + " 'plugin\\n'\n", + " '=\\n'\n", + " \"'nav2_lifecycle_manager::LifecycleManager'\\n\"\n", + " ',\\n'\n", + " 'name\\n'\n", + " '=\\n'\n", + " \"'lifecycle_manager_costmap_filters'\\n\"\n", + " ',\\n'\n", + " 'parameters\\n'\n", + " '=\\n'\n", + " '[{\\n'\n", + " \"'use_sim_time'\\n\"\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'autostart'\\n\"\n", + " ':\\n'\n", + " 'autostart\\n'\n", + " '},\\n'\n", + " '{\\n'\n", + " \"'node_names'\\n\"\n", + " ':\\n'\n", + " 'lifecycle_nodes\\n'\n", + " '}]),\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " ']\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '=\\n'\n", + " 'LaunchDescription\\n'\n", + " '()\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_namespace_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_sim_time_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_autostart_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_params_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_mask_yaml_file_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_use_composition_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'declare_container_name_cmd\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_nodes\\n'\n", + " ')\\n'\n", + " 'ld\\n'\n", + " '.\\n'\n", + " 'add_action\\n'\n", + " '(\\n'\n", + " 'load_composable_nodes\\n'\n", + " ')\\n'\n", + " 'return\\n'\n", + " 'ld',\n", + " 'context': 'In order to enable Keepout Filter in your configuration, both '\n", + " 'servers should be enabled as a lifecycle nodes in Python '\n", + " 'launch-file. It is also possible to add them as Composition '\n", + " 'Nodes to your Navigation Component Container, which might look '\n", + " 'as follows:',\n", + " 'filename': 'OccupancyGrid',\n", + " 'language': 'unknown'},\n", + " {'code': 'costmap_filter_info_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'type\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'filter_info_topic\\n'\n", + " ':\\n'\n", + " '\"/costmap_filter_info\"\\n'\n", + " 'mask_topic\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'base\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'multiplier\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'filter_mask_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'frame_id\\n'\n", + " ':\\n'\n", + " '\"map\"\\n'\n", + " 'topic_name\\n'\n", + " ':\\n'\n", + " '\"/keepout_filter_mask\"\\n'\n", + " 'yaml_filename\\n'\n", + " ':\\n'\n", + " '\"keepout_mask.yaml\"',\n", + " 'context': 'where theparams_filevariable should be set to a YAML-file having '\n", + " 'ROS parameters for Costmap Filter Info Publisher Server and Map '\n", + " 'Server nodes. These parameters and their meaning are listed '\n", + " 'atMap Server / Saverpage. Please, refer to it for more '\n", + " 'information. The example ofparams_filecould be found below:',\n", + " 'filename': 'params_file',\n", + " 'language': 'unknown'},\n", + " {'code': '$\\n'\n", + " 'mkdir\\n'\n", + " '-p\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws/src\\n'\n", + " '$\\n'\n", + " 'git\\n'\n", + " 'clone\\n'\n", + " 'https://github.com/ros-navigation/navigation2_tutorials.git\\n'\n", + " '$\\n'\n", + " 'cd\\n'\n", + " '~/tutorials_ws\\n'\n", + " '$\\n'\n", + " 'colcon\\n'\n", + " 'build\\n'\n", + " '--symlink-install\\n'\n", + " '--packages-select\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " '$\\n'\n", + " 'source\\n'\n", + " '~/tutorials_ws/install/setup.bash\\n'\n", + " '$\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_costmap_filters_demo\\n'\n", + " 'costmap_filter_info.launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml\\n'\n", + " 'mask:\\n'\n", + " '=\\n'\n", + " '`\\n'\n", + " 'pwd\\n'\n", + " '`\\n'\n", + " '/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml\\n'\n", + " 'use_composition:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'Ready-to-go standalone Python launch-script, YAML-file with ROS '\n", + " 'parameters and filter mask example for Keepout Filter could be '\n", + " 'found in anav2_costmap_filters_demodirectory '\n", + " 'ofnavigation2_tutorialsrepository. To simply run Filter Info '\n", + " 'Publisher Server and Map Server tuned on Turtlebot3 standard '\n", + " 'simulation written atGetting Started, build the demo and '\n", + " 'launchcostmap_filter_info.launch.pyas follows:',\n", + " 'filename': 'costmap_filter_info.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap:\\n'\n", + " ' global_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"static_layer\", \"obstacle_layer\", '\n", + " '\"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n'\n", + " '...\\n'\n", + " 'local_costmap:\\n'\n", + " ' local_costmap:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' ...\\n'\n", + " ' plugins: [\"voxel_layer\", \"inflation_layer\"]\\n'\n", + " ' filters: [\"keepout_filter\"]\\n'\n", + " ' ...\\n'\n", + " ' keepout_filter:\\n'\n", + " ' plugin: \"nav2_costmap_2d::KeepoutFilter\"\\n'\n", + " ' enabled: True\\n'\n", + " ' filter_info_topic: \"/costmap_filter_info\"\\n',\n", + " 'context': 'To enableKeepoutFilterwith same mask for both global and local '\n", + " 'costmaps, use the following configuration:',\n", + " 'filename': 'KeepoutFilter',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\ntb3_simulation_launch.py\\n',\n", + " 'context': 'After Costmap Filter Info Publisher Server and Map Server were '\n", + " 'launched and Keepout Filter was enabled for global/local '\n", + " 'costmaps, run Nav2 stack as written inGetting Started:',\n", + " 'filename': 'filters',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Follow Dynamic Point\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "Code Blocks:\n", + "[{'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'After the new path to the dynamic point is computed and '\n", + " 'truncated, it is again passed to the controller via '\n", + " 'theFollowPathnode.\\n'\n", + " 'However, note that it is under aKeepRunningUntilFailuredecorator '\n", + " 'node ensuring the controller continues to execute until a '\n", + " 'failure mode.\\n'\n", + " 'This behavior tree will execute infinitely in time until the '\n", + " 'navigation request is preempted or cancelled.',\n", + " 'filename': 'KeepRunningUntilFailure',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Planner and Controller Servers\n", + "Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice.\n", + "The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment.\n", + "The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station.\n", + "As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server.\n", + "\n", + "## Selecting the Algorithm Plugins\n", + "In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server.\n", + "\n", + "## Planner Server\n", + "The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility.\n", + "As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments.\n", + "One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots.\n", + "Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds.\n", + "There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration.\n", + "\n", + "## Summary\n", + "\n", + "\n", + "## Example Configuration\n", + "An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Controller Server\n", + "The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity.\n", + "TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint.\n", + "Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots.\n", + "Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots.\n", + "The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots.\n", + "\n", + "## Summary\n", + "All of these algorithms work for both circular and non-circular robots.\n", + "\n", + "## Example Configuration\n", + "Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'planner_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'planner_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " \"'GridBased'\\n\"\n", + " ']\\n'\n", + " 'GridBased\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " \"'nav2_navfn_planner::NavfnPlanner'\\n\"\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Non-circular Differential, Non-circular Omnidirectional',\n", + " 'filename': 'SmacLatticeplanner',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'controller_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"FollowPath\"\\n'\n", + " ']\\n'\n", + " 'FollowPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"dwb_core::DWBLocalPlanner\"',\n", + " 'context': 'All of these algorithms work for both circular and non-circular '\n", + " 'robots.',\n", + " 'filename': 'TrajectoryGenerationplugin',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: (STVL) Using an External Costmap Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to load and use an external plugin.\n", + "This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example.\n", + "STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors.\n", + "Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available.\n", + "This tutorial assumes knowledge of navigation and basic understanding of costmaps.\n", + "\n", + "## Costmap2D and STVL\n", + "Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts.\n", + "Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime.\n", + "Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer.\n", + "However, these are simply example plugins offered by the base implementation.\n", + "Another available pluginlib plugin for Costmap2D in Navigation2 is STVL.\n", + "STVL is another 3D perception plugin similar to the Voxel Layer.\n", + "A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration.\n", + "This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x.\n", + "STVL also treats 3D lidars and radars as first class citizens for support.\n", + "The ROSCon talk for STVL can be foundin this video.\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup\n", + "Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed.\n", + "\n", + "## 1- Install STVL\n", + "STVL can be installed in ROS 2 via the ROS Build Farm:\n", + "It can also be built from source by cloning the repository into your Navigation2 workspace:\n", + "\n", + "## 1- Modify Navigation2 Parameter\n", + "STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps.\n", + "For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively:\n", + "To load the STVL plugin, a new plugin name and type must be added.\n", + "For example, if the application required an STVL layer and no obstacle layer, our file would be:\n", + "Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer.\n", + "An example fully-described parameterization of an STVL configuration is:\n", + "Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application.\n", + "Make sure to change both the local and global costmaps.\n", + "Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way.\n", + "\n", + "## 2- Launch Navigation2\n", + "Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2.\n", + "Navigation2 is now using STVL as its 3D sensing costmap layer.\n", + "\n", + "## 3- RVIZ\n", + "With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics.\n", + "Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ']',\n", + " 'context': 'STVL is an optional plugin, like all plugins, in Costmap2D. '\n", + " 'Costmap Plugins in Navigation2 are loaded in '\n", + " 'theplugin_namesandplugin_typesvariables inside of their '\n", + " 'respective costmaps.\\n'\n", + " 'For example, the following will load the static and obstacle '\n", + " 'layer plugins into the namestatic_layerandobstacle_layer, '\n", + " 'respectively:',\n", + " 'filename': 'obstacle_layer',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"stvl_layer\"\\n'\n", + " ']',\n", + " 'context': 'To load the STVL plugin, a new plugin name and type must be '\n", + " 'added.\\n'\n", + " 'For example, if the application required an STVL layer and no '\n", + " 'obstacle layer, our file would be:',\n", + " 'filename': 'plugin:MyPlugin::Plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'stvl_layer\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'voxel_decay\\n'\n", + " ':\\n'\n", + " '15.\\n'\n", + " 'decay_model\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'voxel_size\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'unknown_threshold\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'update_footprint_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'combination_method\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'transform_tolerance\\n'\n", + " ':\\n'\n", + " '0.2\\n'\n", + " 'mapping_mode\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'map_save_duration\\n'\n", + " ':\\n'\n", + " '60.0\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'pointcloud\\n'\n", + " 'pointcloud\\n'\n", + " ':\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " 'PointCloud2\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/intel_realsense_r200_depth/points\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'obstacle_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'min_obstacle_height\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'expected_update_rate\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'observation_persistence\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'inf_is_valid\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'filter\\n'\n", + " ':\\n'\n", + " '\"voxel\"\\n'\n", + " 'voxel_min_points\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " 'clear_after_reading\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'max_z\\n'\n", + " ':\\n'\n", + " '7.0\\n'\n", + " 'min_z\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'vertical_fov_angle\\n'\n", + " ':\\n'\n", + " '0.8745\\n'\n", + " 'horizontal_fov_angle\\n'\n", + " ':\\n'\n", + " '1.048\\n'\n", + " 'decay_acceleration\\n'\n", + " ':\\n'\n", + " '15.0\\n'\n", + " 'model_type\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Similar to the Voxel Layer, after registering the plugin, we can '\n", + " 'add the configuration of the STVL layer under the '\n", + " 'namespacestvl_layer.\\n'\n", + " 'An example fully-described parameterization of an STVL '\n", + " 'configuration is:',\n", + " 'filename': 'stvl_layer',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Foxy to Galactic\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## NavigateToPose Action Feedback updates\n", + "The NavigateToPose action feedback has two improvements:\n", + "\n", + "## NavigateToPose BT-node Interface Changes\n", + "The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion.\n", + "SeeNavigateToPosefor more information.\n", + "\n", + "## NavigateThroughPoses and ComputePathThroughPoses Actions Added\n", + "TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses.\n", + "TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints.\n", + "If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose.\n", + "\n", + "## ComputePathToPose BT-node Interface Changes\n", + "Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal.\n", + "SeeComputePathToPosefor more information.\n", + "\n", + "## ComputePathToPose Action Interface Changes\n", + "These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server.\n", + "\n", + "## BackUp BT-node Interface Changes\n", + "Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward.\n", + "\n", + "## BackUp Recovery Interface Changes\n", + "speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward.\n", + "In both cases negative values are silently inverted.\n", + "\n", + "## Nav2 Controllers and Goal Checker Plugin Interface Changes\n", + "As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin.\n", + "Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place.\n", + "\n", + "## FollowPath goal_checker_id attribute\n", + "For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions.\n", + "Below it is shown an example of goal_checker configuration of the controller_server node.\n", + "\n", + "## Groot Support\n", + "Live Monitoring and Editing of behavior trees with Groot is now possible.\n", + "Switching bt-xmls on the fly through a new goal request is also included.\n", + "This is all done without breaking any APIs.\n", + "Enabled by default.\n", + "\n", + "## New Plugins\n", + "nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to\n", + "perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core.\n", + "Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs.\n", + "Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals.\n", + "WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters.\n", + "All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng.\n", + "Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters.\n", + "Original GitHub tickets:\n", + "\n", + "## Costmap Filters\n", + "A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior.\n", + "Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins:\n", + "Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit.\n", + "High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities.\n", + "\n", + "## SmacPlanner\n", + "A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more.\n", + "Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control.\n", + "TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions.\n", + "\n", + "## ThetaStarPlanner\n", + "A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps.\n", + "This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller.\n", + "\n", + "## RegulatedPurePursuitController\n", + "A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm.\n", + "It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well.\n", + "This variation is specifically targeting service / industrial robot needs.\n", + "It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe.\n", + "It also better follows paths than any other variation currently available of Pure Pursuit.\n", + "It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions.\n", + "It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds.\n", + "There’s more this does, that that’s the general information. See the package’sREADMEfor more.\n", + "\n", + "## Costmap2Dcurrent_Usage\n", + "In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing.\n", + "In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run.\n", + "\n", + "## Standard time units in parameters\n", + "To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds.\n", + "\n", + "## Ray Tracing Parameters\n", + "Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request.\n", + "\n", + "## Obstacle Marking Parameters\n", + "Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below.\n", + "\n", + "## Recovery Action Changes\n", + "The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855.\n", + "\n", + "## Default Behavior Tree Changes\n", + "The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT.\n", + "\n", + "## NavFn Planner Parameters\n", + "The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181.\n", + "\n", + "## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes\n", + "The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204.\n", + "\n", + "## New Behavior Tree Nodes\n", + "A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3.\n", + "Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions.\n", + "These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins.\n", + "Original GitHub tickets:\n", + "Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another).\n", + "\n", + "## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change\n", + "Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below.\n", + "These changes were introduced inpull request 2263.\n", + "\n", + "## ControllerServer New Parameter failure_tolerance\n", + "A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description.\n", + "This change was introduced in thispull request 2264.\n", + "\n", + "## Removed BT XML Launch Configurations\n", + "The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3).\n", + "The use of map subscription QoS launch configuration was also removed, use parameter file.\n", + "This change was introduced in thispull request 2295.\n", + "\n", + "## Nav2 RViz Panel Action Feedback Information\n", + "The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions.\n", + "Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel.\n", + "This feature was introduced in thispull request 2338.\n", + "\n", + "Code Blocks:\n", + "[{'code': '',\n", + " 'context': 'For example: you could use for some specific navigation motion a '\n", + " 'more precise goal checker than the default one that it is used '\n", + " 'in usual motions.',\n", + " 'filename': 'numeric_limitslowest()',\n", + " 'language': 'unknown'},\n", + " {'code': 'controller_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'goal_checker_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"general_goal_checker\"\\n'\n", + " ',\\n'\n", + " '\"precise_goal_checker\"\\n'\n", + " ']\\n'\n", + " 'precise_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'yaw_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25\\n'\n", + " 'general_goal_checker\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_controller::SimpleGoalChecker\"\\n'\n", + " 'xy_goal_tolerance\\n'\n", + " ':\\n'\n", + " '0.25',\n", + " 'context': 'Below it is shown an example of goal_checker configuration of '\n", + " 'the controller_server node.',\n", + " 'filename': 'GridBased',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoint_follower\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'loop_rate\\n'\n", + " ':\\n'\n", + " '20\\n'\n", + " 'stop_on_failure\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " 'waypoint_task_executor_plugin\\n'\n", + " ':\\n'\n", + " '\"wait_at_waypoint\"\\n'\n", + " 'wait_at_waypoint\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_waypoint_follower::WaitAtWaypoint\"\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'waypoint_pause_duration\\n'\n", + " ':\\n'\n", + " '0',\n", + " 'context': 'Loading a plugin of this type is done '\n", + " 'throughnav2_bringup/params/nav2_param.yaml, by specifying '\n", + " 'plugin’s name, type and it’s used parameters.',\n", + " 'filename': 'nav2_bringup/params/nav2_param.yaml',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigating Using GPS Localization\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot.\n", + "\n", + "## Requirements\n", + "It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz:\n", + "The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment.\n", + "This is available in ROS 2 Iron and newer.\n", + "You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information.\n", + "\n", + "## GPS Localization Overview\n", + "GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude.\n", + "Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows.\n", + "However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like:\n", + "Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right?\n", + "To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America.\n", + "robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up.\n", + "In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position.\n", + "Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction.\n", + "When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north.\n", + "Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because:\n", + "Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good.\n", + "For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others).\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 0- Setup Gazebo World\n", + "To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world:\n", + "To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix:\n", + "Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link\n", + "Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching:\n", + "A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements\n", + "\n", + "## 1- Setup GPS Localization system\n", + "Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc).\n", + "In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it.\n", + "We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs.\n", + "Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node.\n", + "\n", + "## Local Odometry\n", + "The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters:\n", + "Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu:\n", + "\n", + "## Global Odometry\n", + "The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message:\n", + "\n", + "## Navsat Transform\n", + "The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice.\n", + "In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system.\n", + "The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data.\n", + "Here’s the full configuration for thenavsat_transformnode:\n", + "\n", + "## Localization Testing\n", + "As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running:\n", + "On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures.\n", + "You should see the window below after properly setting the API key:\n", + "Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot:\n", + "When you have everything up and running, start teleoperating the Turtlebot and check that:\n", + "The gif below shows what you should see:\n", + "Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities:\n", + "\n", + "## 2- Setup Navigation system\n", + "Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file.\n", + "There are three main possible setups for the global costmap:\n", + "We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot:\n", + "The gif below shows what you should see Nav2 navigating the robot autonomously!\n", + "\n", + "## 3- Interactive GPS Waypoint Follower\n", + "Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup!\n", + "For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type:\n", + "You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles:\n", + "\n", + "## 4- Logged GPS Waypoint Follower & Waypoint Logging\n", + "Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format:\n", + "Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type:\n", + "If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows:\n", + "After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage.\n", + "To run this node source your workspace and with the rest of the system running type:\n", + "You should now see the robot following the waypoints you previously logged:\n", + "\n", + "## Conclusion\n", + "This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments.\n", + "The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case.\n", + "Happy outdoors navigating!\n", + "\n", + "Code Blocks:\n", + "[{'code': 'source\\n'\n", + " '/opt/ros//setup.bash\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-robot-localization\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-mapviz-plugins\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros-\\n'\n", + " '$ROS_DISTRO\\n'\n", + " '-tile-map\\n',\n", + " 'context': 'It is assumed ROS2 and Nav2 dependent packages are installed or '\n", + " 'built locally. Additionally you will have to install '\n", + " 'robot_localization and mapviz:',\n", + " 'filename': 'use_cancel_deceleration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " 'EARTH_WGS84\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '38.161479\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '-122.454630\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '488.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '180\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To navigate using GPS we first need to create an outdoors Gazebo '\n", + " 'world with a robot having a GPS sensor to setup for navigation. '\n", + " 'For this tutorial we will be using theSonoma Racewaybecause its '\n", + " 'aligned with the real location. A sample world has been '\n", + " 'setuphereusing gazebo’s spherical coordinates plugin, which '\n", + " 'creates a local tangent plane centered in the set geographic '\n", + " 'origin and provides latitude, longitude and altitude coordinates '\n", + " 'for each point in the world:',\n", + " 'filename': '+z',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '1\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '~/out:=/gps/fix\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'To get GPS readings from Gazebo we need to create a robot model '\n", + " 'with a GPS sensor. An updated Turtlebot model with such sensor '\n", + " 'is provided in thetutorial repo, it outputsNavSatFixmessages on '\n", + " 'the topic/gps/fix:',\n", + " 'filename': '/gps/fix',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Additionally, since we added a new GPS sensor in thegps_linkwe '\n", + " 'need to add a joint for this link that publishes a static '\n", + " 'transform w.r.t.base_link',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gazebo_gps_world.launch.py\\n',\n", + " 'context': 'Build thenav2_gps_waypoint_follower_demopackage, source your '\n", + " 'workspace and test your gazebo world is properly set up by '\n", + " 'launching:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_odom\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'odom',\n", + " 'context': 'The local odometry is provided by theekf_filter_node_odom, which '\n", + " 'publishes the transform betweenodomandbase_footprint, the base '\n", + " 'frame of the turtlebot’s diff drive plugin in gazebo. The robot '\n", + " 'state publisher provides a static transform '\n", + " 'betweenbase_footprintandbase_link, however make sure to set the '\n", + " 'base frame properly in RL according to your configuration. Note '\n", + " 'that the EKFs are set to work in 2D mode, this is because nav2’s '\n", + " 'costmap environment representation is 2-Dimensional, and several '\n", + " 'layers rely on thebase_linkframe being on the same plane as '\n", + " 'their global frame for the height related parameters to make '\n", + " 'sense. This is encoded in the following parameters:',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'odom0\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'odom0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']\\n'\n", + " 'imu0\\n'\n", + " ':\\n'\n", + " 'imu\\n'\n", + " 'imu0_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'Since perREP 105the position of the robot in theodomframe has to '\n", + " 'be continuous over time, in this filter we just want to fuse the '\n", + " 'robot’s speed measured by its wheels published/odom, and the imu '\n", + " 'heading published on/imu:',\n", + " 'filename': '/imu',\n", + " 'language': 'unknown'},\n", + " {'code': 'ekf_filter_node_map\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'two_d_mode\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_tf\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'base_link_frame\\n'\n", + " ':\\n'\n", + " 'base_footprint\\n'\n", + " 'world_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'odom1\\n'\n", + " ':\\n'\n", + " 'odometry/gps\\n'\n", + " 'odom1_config\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'true\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ',\\n'\n", + " 'false\\n'\n", + " ']',\n", + " 'context': 'The global odometry is provided by theekf_filter_node_map, which '\n", + " 'publishes the transform betweenmapandbase_footprint. This EKF is '\n", + " 'set to work in 2D mode as well. In addition to the IMU and wheel '\n", + " 'odometry data, this filter takes in the odometry output of the '\n", + " 'gps, published by thenavsat_transformnode on/odometry/gpsas an '\n", + " 'odometry message:',\n", + " 'filename': '/odometry/gps',\n", + " 'language': 'unknown'},\n", + " {'code': 'navsat_transform\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'frequency\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " 'delay\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " 'magnetic_declination_radians\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'yaw_offset\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " 'zero_altitude\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'broadcast_utm_transform\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'publish_filtered_gps\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'use_odometry_yaw\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " 'wait_for_datum\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, '\n", + " '[lat, lon, yaw]',\n", + " 'context': 'Here’s the full configuration for thenavsat_transformnode:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'dual_ekf_navsat.launch.py\\n',\n", + " 'context': 'As a sanity check that everything is working correctly, launch '\n", + " 'RL’s launch file while Gazebo is still running:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_gps_waypoint_follower_demo\\nmapviz.launch.py\\n',\n", + " 'context': 'On a different terminal launch mapviz using the pre-builtconfig '\n", + " 'filein the repo.Get a bing maps API keyand use it to display '\n", + " 'satellite pictures.',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\nteleop_twist_keyboard\\nteleop_twist_keyboard\\n',\n", + " 'context': 'Finally run the teleop twist keyboard node to teleoperate the '\n", + " 'simulated Turtlebot:',\n", + " 'filename': 'navsat_transform',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50',\n", + " 'context': 'Rolling(Used in the tutorial): Outdoors environments can get '\n", + " 'quite big, to a degree that it may not be practical to represent '\n", + " 'them on a single costmap. For that reason in this tutorial we '\n", + " 'use a rolling global costmap that is big enough for fitting '\n", + " 'successive pairs of waypoints. In this case you may or may not '\n", + " 'choose to use a static layer, however if you do make sure to fix '\n", + " 'thedatumof the navsat_transform so GPS coordinates always have '\n", + " 'the same cartesian representation on your map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Size and position from static map: You may also choose to keep '\n", + " 'Nav2 default setup and have the global costmap be sized and '\n", + " 'positioned according to a pre-built map by adding a static layer '\n", + " 'and usingmap_server. In this case you also need to make sure '\n", + " 'there’s consistency in yourdatumand the origin of the map.',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'global_costmap\\n'\n", + " ':\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '...\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '50\\n'\n", + " 'origin_x\\n'\n", + " ':\\n'\n", + " '25.0\\n'\n", + " 'origin_y\\n'\n", + " ':\\n'\n", + " '25.0',\n", + " 'context': 'Static position and size: Finally, depending on your application '\n", + " 'you may still choose to use a fixed global costmap if you have a '\n", + " 'restricted operating environment you know beforehand, just '\n", + " 'remember to make it fit all the potential locations the robot '\n", + " 'may visit. In this case you need to set the size and origin '\n", + " 'position in the parameters:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_follower.launch.py\\n'\n", + " 'use_rviz:\\n'\n", + " '=\\n'\n", + " 'True\\n',\n", + " 'context': 'We provide aNav2 params filewith the rolling costmap setup and '\n", + " 'alaunch fileto put it all together. Remember that the GPS setup '\n", + " 'of robot_localization was just a means for setting up the global '\n", + " 'localization system, however Nav2 is still a cartesian '\n", + " 'navigation stack and you may still use all its cartesian tools. '\n", + " 'To confirm that everything is working, launch the provided file '\n", + " '(this launches gazebo and RL as well so close them if you have '\n", + " 'them running from the previous steps) and use rviz to send a '\n", + " 'goal to the robot:',\n", + " 'filename': 'datum',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'interactive_waypoint_follower\\n',\n", + " 'context': 'For this purpose we provide '\n", + " 'theinteractive_waypoint_followerpython node, which subscribes to '\n", + " 'mapviz’s topic and calls the/follow_gps_waypointsaction server '\n", + " 'with the clicked point as goal using '\n", + " 'theBasicNavigatorinnav2_simple_commander. To run it source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'nav2_simple_commander',\n", + " 'language': 'unknown'},\n", + " {'code': 'waypoints\\n'\n", + " ':\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161491054181276\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.45464431092836\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '-\\n'\n", + " 'latitude\\n'\n", + " ':\\n'\n", + " '38.161587576524845\\n'\n", + " 'longitude\\n'\n", + " ':\\n'\n", + " '-122.4547994038464\\n'\n", + " 'yaw\\n'\n", + " ':\\n'\n", + " '1.57',\n", + " 'context': 'Finally let’s make a robot go through a set of predefined GPS '\n", + " 'waypoints. We provide awaypoint logging toolthat subscribes to '\n", + " 'the robot’s GPS and IMU and offers a simple GUI to save the '\n", + " 'robot coordinates and heading on demand to ayamlfile with the '\n", + " 'format:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'gps_waypoint_logger\\n'\n", + " '\\n',\n", + " 'context': 'Let’s log some waypoints for the robot to follow. Source your '\n", + " 'workspace and with the rest of the system running type:',\n", + " 'filename': 'yaml',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_gps_waypoint_follower_demo\\n'\n", + " 'logged_waypoint_follower\\n'\n", + " '\\n',\n", + " 'context': 'To run this node source your workspace and with the rest of the '\n", + " 'system running type:',\n", + " 'filename': 'nav2_gps_waypoint_follower_demo',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Setting Up Sensors\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Sensor Introduction\n", + "Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment.\n", + "Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image.\n", + "Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few.\n", + "Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage.\n", + "\n", + "## Common Sensor Messages\n", + "In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz.\n", + "\n", + "## sensor_msgs/LaserScan\n", + "This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception.\n", + "\n", + "## sensor_msgs/PointCloud2\n", + "This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more.\n", + "\n", + "## sensor_msgs/Range\n", + "This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message.\n", + "\n", + "## sensor_msgs/Image\n", + "This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values.\n", + "\n", + "## Simulating Sensors using Gazebo\n", + "To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use.\n", + "To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo.\n", + "\n", + "## Adding Gazebo Plugins to a URDF\n", + "Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag.\n", + "In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages.\n", + "Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor.\n", + "Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera.\n", + "\n", + "## Launch and Build Files\n", + "To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects.\n", + "Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly.\n", + "To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf.\n", + "Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description():\n", + "Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below.\n", + "We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We can now build and run our project. Navigate to the root of the project and execute the following lines:\n", + "RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below.\n", + "In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct:\n", + "Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below.\n", + "Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world.\n", + "To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively:\n", + "After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below.\n", + "You should also see thesensor_msgs/PointCloud2, as shown below.\n", + "\n", + "## Mapping and Localization\n", + "Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information.\n", + "Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan.\n", + "In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below.\n", + "You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section.\n", + "\n", + "## Costmap 2D\n", + "The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage.\n", + "The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d.\n", + "The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins.\n", + "\n", + "## Configuring nav2_costmap_2d\n", + "In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2.\n", + "In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance.\n", + "The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer.\n", + "For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined.\n", + "For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan.\n", + "Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot.\n", + "For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively.\n", + "For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius.\n", + "For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner.\n", + "Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up.\n", + "\n", + "## Build, Run and Verification\n", + "We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information.\n", + "Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap.\n", + "After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output.\n", + "\n", + "## Launching Description Nodes, RViz and Gazebo\n", + "Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below.\n", + "RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz.\n", + "\n", + "## Launching slam_toolbox\n", + "To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command:\n", + "We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines:\n", + "Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform.\n", + "We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below.\n", + "We can also check that the transforms are correct by executing the following lines in a new terminal:\n", + "Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below:\n", + "\n", + "## Launching Nav2\n", + "First, Make sure you have installed the Nav2 packages by executing the following:\n", + "We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following:\n", + "Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation.\n", + "After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active.\n", + "\n", + "## Visualizing Costmaps in RViz\n", + "Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz.\n", + "To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo.\n", + "To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below.\n", + "To visualize the voxel representation of the detected object, open a new terminal and execute the following lines:\n", + "The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below.\n", + "Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world:\n", + "\n", + "## Conclusion\n", + "In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks.\n", + "We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz.\n", + "Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '251\\n'\n", + " '\\n'\n", + " '252\\n'\n", + " '\\n'\n", + " '253\\n'\n", + " '\\n'\n", + " '254\\n'\n", + " '\\n'\n", + " '255\\n'\n", + " '\\n'\n", + " '256\\n'\n", + " '\\n'\n", + " '257\\n'\n", + " '258\\n'\n", + " '\\n'\n", + " '259\\n'\n", + " '\\n'\n", + " '260\\n'\n", + " '\\n'\n", + " '261\\n'\n", + " '\\n'\n", + " '262\\n'\n", + " '\\n'\n", + " '263\\n'\n", + " '\\n'\n", + " '264\\n'\n", + " '265\\n'\n", + " '\\n'\n", + " '266\\n'\n", + " '\\n'\n", + " '267\\n'\n", + " '\\n'\n", + " '268\\n'\n", + " '\\n'\n", + " '269\\n'\n", + " '\\n'\n", + " '270\\n'\n", + " '\\n'\n", + " '271\\n'\n", + " '\\n'\n", + " '272\\n'\n", + " '273\\n'\n", + " '\\n'\n", + " '274\\n'\n", + " '\\n'\n", + " '275\\n'\n", + " '\\n'\n", + " '276\\n'\n", + " '\\n'\n", + " '277\\n'\n", + " '\\n'\n", + " '278\\n'\n", + " '279\\n'\n", + " '\\n'\n", + " '280\\n'\n", + " '\\n'\n", + " '281\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '282\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '283\\n'\n", + " '\\n'\n", + " '5\\n'\n", + " '\\n'\n", + " '284\\n'\n", + " '\\n'\n", + " '285\\n'\n", + " '\\n'\n", + " '286\\n'\n", + " '\\n'\n", + " '287\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '288\\n'\n", + " '\\n'\n", + " '1.000000\\n'\n", + " '\\n'\n", + " '289\\n'\n", + " '\\n'\n", + " '0.000000\\n'\n", + " '\\n'\n", + " '290\\n'\n", + " '\\n'\n", + " '6.280000\\n'\n", + " '\\n'\n", + " '291\\n'\n", + " '\\n'\n", + " '292\\n'\n", + " '\\n'\n", + " '293\\n'\n", + " '\\n'\n", + " '294\\n'\n", + " '\\n'\n", + " '0.120000\\n'\n", + " '\\n'\n", + " '295\\n'\n", + " '\\n'\n", + " '3.5\\n'\n", + " '\\n'\n", + " '296\\n'\n", + " '\\n'\n", + " '0.015000\\n'\n", + " '\\n'\n", + " '297\\n'\n", + " '\\n'\n", + " '298\\n'\n", + " '\\n'\n", + " '299\\n'\n", + " '\\n'\n", + " 'gaussian\\n'\n", + " '\\n'\n", + " '300\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '301\\n'\n", + " '\\n'\n", + " '0.01\\n'\n", + " '\\n'\n", + " '302\\n'\n", + " '\\n'\n", + " '303\\n'\n", + " '\\n'\n", + " '304\\n'\n", + " '\\n'\n", + " '305\\n'\n", + " '\\n'\n", + " '306\\n'\n", + " '\\n'\n", + " '~/out:=scan\\n'\n", + " '\\n'\n", + " '307\\n'\n", + " '\\n'\n", + " '308\\n'\n", + " '\\n'\n", + " 'sensor_msgs/LaserScan\\n'\n", + " '\\n'\n", + " '309\\n'\n", + " '\\n'\n", + " 'lidar_link\\n'\n", + " '\\n'\n", + " '310\\n'\n", + " '\\n'\n", + " '311\\n'\n", + " '\\n'\n", + " '312\\n'\n", + " '',\n", + " 'context': 'Let us first add a lidar sensor tosam_bot. Open the URDF '\n", + " 'file,src/description/sam_bot_description.urdfand paste the '\n", + " 'following lines before thetag.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': '314\\n'\n", + " '\\n'\n", + " '315\\n'\n", + " '\\n'\n", + " '316\\n'\n", + " '\\n'\n", + " '317\\n'\n", + " '\\n'\n", + " '318\\n'\n", + " '\\n'\n", + " '319\\n'\n", + " '\\n'\n", + " '320\\n'\n", + " '\\n'\n", + " '321\\n'\n", + " '322\\n'\n", + " '\\n'\n", + " '323\\n'\n", + " '\\n'\n", + " '324\\n'\n", + " '\\n'\n", + " '325\\n'\n", + " '\\n'\n", + " '326\\n'\n", + " '\\n'\n", + " '327\\n'\n", + " '\\n'\n", + " '328\\n'\n", + " '329\\n'\n", + " '\\n'\n", + " '330\\n'\n", + " '\\n'\n", + " '331\\n'\n", + " '\\n'\n", + " '332\\n'\n", + " '\\n'\n", + " '333\\n'\n", + " '\\n'\n", + " '334\\n'\n", + " '\\n'\n", + " '335\\n'\n", + " '336\\n'\n", + " '\\n'\n", + " '337\\n'\n", + " '\\n'\n", + " '338\\n'\n", + " '\\n'\n", + " '339\\n'\n", + " '\\n'\n", + " '340\\n'\n", + " '\\n'\n", + " '341\\n'\n", + " '342\\n'\n", + " '\\n'\n", + " '343\\n'\n", + " '344\\n'\n", + " '\\n'\n", + " '345\\n'\n", + " '\\n'\n", + " '346\\n'\n", + " '\\n'\n", + " '347\\n'\n", + " '\\n'\n", + " '348\\n'\n", + " '\\n'\n", + " '349\\n'\n", + " '350\\n'\n", + " '\\n'\n", + " '351\\n'\n", + " '\\n'\n", + " '352\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '353\\n'\n", + " '\\n'\n", + " '30.0\\n'\n", + " '\\n'\n", + " '354\\n'\n", + " '\\n'\n", + " '355\\n'\n", + " '\\n'\n", + " '1.047198\\n'\n", + " '\\n'\n", + " '356\\n'\n", + " '\\n'\n", + " '357\\n'\n", + " '\\n'\n", + " '640\\n'\n", + " '\\n'\n", + " '358\\n'\n", + " '\\n'\n", + " '480\\n'\n", + " '\\n'\n", + " '359\\n'\n", + " '\\n'\n", + " 'R8G8B8\\n'\n", + " '\\n'\n", + " '360\\n'\n", + " '\\n'\n", + " '361\\n'\n", + " '\\n'\n", + " '362\\n'\n", + " '\\n'\n", + " '0.05\\n'\n", + " '\\n'\n", + " '363\\n'\n", + " '\\n'\n", + " '3\\n'\n", + " '\\n'\n", + " '364\\n'\n", + " '\\n'\n", + " '365\\n'\n", + " '\\n'\n", + " '366\\n'\n", + " '\\n'\n", + " '367\\n'\n", + " '\\n'\n", + " '0.2\\n'\n", + " '\\n'\n", + " '368\\n'\n", + " '\\n'\n", + " 'true\\n'\n", + " '\\n'\n", + " '369\\n'\n", + " '\\n'\n", + " '0.0\\n'\n", + " '\\n'\n", + " '370\\n'\n", + " '\\n'\n", + " 'camera_depth_frame\\n'\n", + " '\\n'\n", + " '371\\n'\n", + " '\\n'\n", + " '0.5\\n'\n", + " '\\n'\n", + " '372\\n'\n", + " '\\n'\n", + " '3.0\\n'\n", + " '\\n'\n", + " '373\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '374\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '375\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '376\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '377\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '378\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '379\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '380\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '381\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '382\\n'\n", + " '\\n'\n", + " '0\\n'\n", + " '\\n'\n", + " '383\\n'\n", + " '\\n'\n", + " '384\\n'\n", + " '\\n'\n", + " '385\\n'\n", + " '',\n", + " 'context': 'Next, let us add a depth camera tosam_bot. Paste the following '\n", + " 'lines after thetag of the lidar sensor.',\n", + " 'filename': '',\n", + " 'language': 'unknown'},\n", + " {'code': \"world_path\\n=\\nos.path.join\\n(\\npkg_share,\\n'world/my_world.sdf'\\n)\",\n", + " 'context': 'Now, let us edit our launch file,launch/display.launch.py, to '\n", + " 'launch Gazebo with the world we just created. First, add the '\n", + " 'path ofmy_world.sdfby adding the following lines inside '\n", + " 'thegenerate_launch_description():',\n", + " 'filename': 'generate_launch_description()',\n", + " 'language': 'unknown'},\n", + " {'code': 'launch.actions.ExecuteProcess\\n'\n", + " '(\\n'\n", + " 'cmd\\n'\n", + " '=[\\n'\n", + " \"'gazebo'\\n\"\n", + " ',\\n'\n", + " \"'--verbose'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_init.so'\\n\"\n", + " ',\\n'\n", + " \"'-s'\\n\"\n", + " ',\\n'\n", + " \"'libgazebo_ros_factory.so'\\n\"\n", + " ',\\n'\n", + " 'world_path\\n'\n", + " ']\\n'\n", + " ',\\n'\n", + " 'output\\n'\n", + " '=\\n'\n", + " \"'screen'\\n\"\n", + " ')\\n'\n", + " ',\\n',\n", + " 'context': 'Lastly, add the world path in '\n", + " \"thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown \"\n", + " 'below.',\n", + " 'filename': \"launch.actions.ExecuteProcess(cmd=['gazebo',...\",\n", + " 'language': 'unknown'},\n", + " {'code': 'install\\n'\n", + " '(\\n'\n", + " 'DIRECTORY\\n'\n", + " 'src\\n'\n", + " 'launch\\n'\n", + " 'rviz\\n'\n", + " 'config\\n'\n", + " 'world\\n'\n", + " '\\n'\n", + " 'DESTINATION\\n'\n", + " 'share/\\n'\n", + " '${\\n'\n", + " 'PROJECT_NAME\\n'\n", + " '}\\n'\n", + " ')',\n", + " 'context': 'We also have to add theworlddirectory to ourCMakeLists.txtfile. '\n", + " 'OpenCmakeLists.txtand append theworlddirectory inside the '\n", + " 'install(DIRECTORY…), as shown in the snippet below.',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'We can now build and run our project. Navigate to the root of '\n", + " 'the project and execute the following lines:',\n", + " 'filename': 'world',\n", + " 'language': 'unknown'},\n", + " {'code': ' 1\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 2\\n'\n", + " 'global_costmap\\n'\n", + " ':\\n'\n", + " ' 3\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " ' 4\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 5\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " ' 6\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " ' 7\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " ' 8\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " ' 9\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '10\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '11\\n'\n", + " 'track_unknown_space\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '12\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '13\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"static_layer\"\\n'\n", + " ',\\n'\n", + " '\"obstacle_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '14\\n'\n", + " 'static_layer\\n'\n", + " ':\\n'\n", + " '15\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::StaticLayer\"\\n'\n", + " '16\\n'\n", + " 'map_subscribe_transient_local\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '17\\n'\n", + " 'obstacle_layer\\n'\n", + " ':\\n'\n", + " '18\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " '19\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '20\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '21\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '22\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '23\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '24\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '25\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '26\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '27\\n'\n", + " 'raytrace_max_range\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '28\\n'\n", + " 'raytrace_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '29\\n'\n", + " 'obstacle_max_range\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '30\\n'\n", + " 'obstacle_min_range\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '31\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '32\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '33\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '34\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '35\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '36\\n'\n", + " '37\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '38\\n'\n", + " 'local_costmap\\n'\n", + " ':\\n'\n", + " '39\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " '40\\n'\n", + " 'update_frequency\\n'\n", + " ':\\n'\n", + " '5.0\\n'\n", + " '41\\n'\n", + " 'publish_frequency\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '42\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " '43\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " '44\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '45\\n'\n", + " 'rolling_window\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '46\\n'\n", + " 'width\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '47\\n'\n", + " 'height\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '48\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '49\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.22\\n'\n", + " '50\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']\\n'\n", + " '51\\n'\n", + " 'voxel_layer\\n'\n", + " ':\\n'\n", + " '52\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::VoxelLayer\"\\n'\n", + " '53\\n'\n", + " 'enabled\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '54\\n'\n", + " 'publish_voxel_map\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '55\\n'\n", + " 'origin_z\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '56\\n'\n", + " 'z_resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '57\\n'\n", + " 'z_voxels\\n'\n", + " ':\\n'\n", + " '16\\n'\n", + " '58\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '59\\n'\n", + " 'mark_threshold\\n'\n", + " ':\\n'\n", + " '0\\n'\n", + " '60\\n'\n", + " 'observation_sources\\n'\n", + " ':\\n'\n", + " 'scan\\n'\n", + " '61\\n'\n", + " 'scan\\n'\n", + " ':\\n'\n", + " '62\\n'\n", + " 'topic\\n'\n", + " ':\\n'\n", + " '/scan\\n'\n", + " '63\\n'\n", + " 'max_obstacle_height\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " '64\\n'\n", + " 'clearing\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '65\\n'\n", + " 'marking\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '66\\n'\n", + " 'data_type\\n'\n", + " ':\\n'\n", + " '\"LaserScan\"\\n'\n", + " '67\\n'\n", + " 'inflation_layer\\n'\n", + " ':\\n'\n", + " '68\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_costmap_2d::InflationLayer\"\\n'\n", + " '69\\n'\n", + " 'cost_scaling_factor\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '70\\n'\n", + " 'inflation_radius\\n'\n", + " ':\\n'\n", + " '0.55\\n'\n", + " '71\\n'\n", + " 'always_send_full_costmap\\n'\n", + " ':\\n'\n", + " 'True',\n", + " 'context': 'In this subsection, we will show an example configuration '\n", + " 'ofnav2_costmap_2dsuch that it uses the information provided by '\n", + " 'the lidar sensor ofsam_bot. We will show an example '\n", + " 'configuration that uses static layer, obstacle layer, voxel '\n", + " 'layer, and inflation layer. We set both the obstacle and voxel '\n", + " 'layer to use theLaserScanmessages published to the/scantopic by '\n", + " 'the lidar sensor. We also set some of the basic parameters to '\n", + " 'define how the detected obstacles are reflected in the costmap. '\n", + " 'Note that this configuration is to be included in the '\n", + " 'configuration file of Nav2.',\n", + " 'filename': '/scan',\n", + " 'language': 'unknown'},\n", + " {'code': 'obstacle_layer:\\n'\n", + " '\\n'\n", + " 'plugin:\\n'\n", + " '\"nav2_costmap_2d::ObstacleLayer\"\\n'\n", + " 'enabled:\\n'\n", + " 'True\\n'\n", + " '\\n'\n", + " 'observation_sources:\\n'\n", + " 'scan\\n'\n", + " 'pointcloud\\n'\n", + " '\\n'\n", + " 'scan:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/scan\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"LaserScan\"\\n'\n", + " 'pointcloud:\\n'\n", + " '\\n'\n", + " 'topic:\\n'\n", + " '/depth_camera/points\\n'\n", + " '\\n'\n", + " 'data_type:\\n'\n", + " '\"PointCloud2\"',\n", + " 'context': 'Note that the obstacle layer and voxel layer can use either or '\n", + " 'bothLaserScanandPointCloud2as theirdata_typebut it is set '\n", + " 'toLaserScanby default. The code snippet below shows an example '\n", + " 'of using both theLaserScanandPointCloud2as the sensor sources. '\n", + " 'This may be particularly useful when setting up your own '\n", + " 'physical robot.',\n", + " 'filename': 'PointCloud2',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'Let us now launch our Robot Description Nodes, RViz and Gazebo '\n", + " 'through the launch filedisplay.launch.py. Open a new terminal '\n", + " 'and execute the lines below.',\n", + " 'filename': 'display.launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\napt\\ninstall\\nros--slam-toolbox\\n',\n", + " 'context': 'To be able to launchslam_toolbox, make sure that you have '\n", + " 'installed theslam_toolboxpackage by executing the following '\n", + " 'command:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nslam_toolbox\\nonline_async_launch.py\\n',\n", + " 'context': 'We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the '\n", + " 'package’s built-in launch files. Open a new terminal and then '\n", + " 'execute the following lines:',\n", + " 'filename': 'slam_toolbox',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nrun\\ntf2_tools\\nview_frames.py\\n',\n", + " 'context': 'We can also check that the transforms are correct by executing '\n", + " 'the following lines in a new terminal:',\n", + " 'filename': '/map',\n", + " 'language': 'unknown'},\n", + " {'code': 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--navigation2\\n'\n", + " 'sudo\\n'\n", + " 'apt\\n'\n", + " 'install\\n'\n", + " 'ros--nav2-bringup\\n',\n", + " 'context': 'First, Make sure you have installed the Nav2 packages by '\n", + " 'executing the following:',\n", + " 'filename': 'frames.pdf',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\nlaunch\\nnav2_bringup\\nnavigation_launch.py\\n',\n", + " 'context': 'We will now launch Nav2 using thenav2_bringup’s built-in launch '\n", + " 'file,navigation_launch.py. Open a new terminal and execute the '\n", + " 'following:',\n", + " 'filename': 'navigation_launch.py',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'nav2_costmap_2d\\n'\n", + " 'nav2_costmap_2d_markers\\n'\n", + " 'voxel_grid:\\n'\n", + " '=\\n'\n", + " '/local_costmap/voxel_grid\\n'\n", + " 'visualization_marker:\\n'\n", + " '=\\n'\n", + " '/my_marker\\n',\n", + " 'context': 'To visualize the voxel representation of the detected object, '\n", + " 'open a new terminal and execute the following lines:',\n", + " 'filename': 'costmap',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Behavior Server\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior Server Parameters\n", + "\n", + "\n", + "## Default Plugins\n", + "When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded:\n", + "\n", + "## Spin Behavior Parameters\n", + "Spin distance is given from the action request\n", + "\n", + "## BackUp Behavior Parameters\n", + "Backup distance, speed and time_allowance is given from the action request.\n", + "\n", + "## DriveOnHeading Behavior Parameters\n", + "DriveOnHeading distance, speed and time_allowance is given from the action request.\n", + "\n", + "## AssistedTeleop Behavior Parameters\n", + "AssistedTeleop time_allowance is given in the action request\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"',\n", + " 'context': 'Example:',\n", + " 'filename': 'plugin',\n", + " 'language': 'unknown'},\n", + " {'code': 'behavior_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'local_costmap_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/costmap_raw\\n'\n", + " 'local_footprint_topic\\n'\n", + " ':\\n'\n", + " 'local_costmap/published_footprint\\n'\n", + " 'global_costmap_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/costmap_raw\\n'\n", + " 'global_footprint_topic\\n'\n", + " ':\\n'\n", + " 'global_costmap/published_footprint\\n'\n", + " 'cycle_frequency\\n'\n", + " ':\\n'\n", + " '10.0\\n'\n", + " 'behavior_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"spin\"\\n'\n", + " ',\\n'\n", + " '\"backup\"\\n'\n", + " ',\\n'\n", + " '\"drive_on_heading\"\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " '\"assisted_teleop\"\\n'\n", + " ']\\n'\n", + " 'spin\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Spin\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'backup\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::BackUp\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'drive_on_heading\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::DriveOnHeading\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'wait\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::Wait\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'assisted_teleop\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_behaviors::AssistedTeleop\"\\n'\n", + " '# In Iron and older versions, \"/\" was used instead of \"::\"\\n'\n", + " 'local_frame\\n'\n", + " ':\\n'\n", + " 'odom\\n'\n", + " 'global_frame\\n'\n", + " ':\\n'\n", + " 'map\\n'\n", + " 'robot_base_frame\\n'\n", + " ':\\n'\n", + " 'base_link\\n'\n", + " 'transform_timeout\\n'\n", + " ':\\n'\n", + " '0.1\\n'\n", + " 'simulate_ahead_time\\n'\n", + " ':\\n'\n", + " '2.0\\n'\n", + " 'max_rotational_vel\\n'\n", + " ':\\n'\n", + " '1.0\\n'\n", + " 'min_rotational_vel\\n'\n", + " ':\\n'\n", + " '0.4\\n'\n", + " 'rotational_acc_lim\\n'\n", + " ':\\n'\n", + " '3.2\\n'\n", + " 'enable_stamped_cmd_vel\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# default false in Jazzy or older',\n", + " 'context': 'Whether to use geometry_msgs::msg::Twist or '\n", + " 'geometry_msgs::msg::TwistStamped velocity data.\\n'\n", + " 'True uses TwistStamped, false uses Twist.\\n'\n", + " 'Note: This parameter is defaultfalsein Jazzy or older! Kilted or '\n", + " 'newer usesTwistStampedby default.',\n", + " 'filename': 'TwistStamped',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: StoppedGoalChecker\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Parameters\n", + ": nav2_controller plugin name defined in thegoal_checker_plugin_idparameter inController Server.\n", + "\n", + "=== Document ===\n", + "Title: Setting Up the Robot’s Footprint\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Footprint Introduction\n", + "The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans.\n", + "The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used.\n", + "For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization.\n", + "For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot.\n", + "Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers.\n", + "\n", + "## Configuring the Robot’s Footprint\n", + "In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps.\n", + "Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot.\n", + "Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot.\n", + "For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below.\n", + "\n", + "## Build, Run and Verification\n", + "We will now confirm that we have properly set upsam_bot’s footprint.\n", + "First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below.\n", + "After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor.\n", + "Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below.\n", + "Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors.\n", + "Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following:\n", + "We should now be able to visualize the footprints in RViz, which will be discussed in the next section.\n", + "\n", + "## Visualizing Footprint in RViz\n", + "To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot:\n", + "On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below.\n", + "Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot:\n", + "\n", + "## Conclusion\n", + "In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function.\n", + "As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz.\n", + "\n", + "Code Blocks:\n", + "[{'code': '188\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05\\n'\n", + " '189\\n'\n", + " 'footprint\\n'\n", + " ':\\n'\n", + " '\"[\\n'\n", + " '[0.21,\\n'\n", + " '0.195],\\n'\n", + " '[0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '-0.195],\\n'\n", + " '[-0.21,\\n'\n", + " '0.195]\\n'\n", + " ']\"\\n'\n", + " '190\\n'\n", + " 'plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"voxel_layer\"\\n'\n", + " ',\\n'\n", + " '\"inflation_layer\"\\n'\n", + " ']',\n", + " 'context': 'Below is the code snippet fromnav2_params.yamldefining the local '\n", + " 'costmap footprint. In this configuration file, '\n", + " 'thefootprintparameter of the local costmap has already been set '\n", + " 'with a rectangular-shaped footprint. This box is centered at '\n", + " 'thebase_linkframe ofsam_bot.',\n", + " 'filename': 'sam_bot',\n", + " 'language': 'unknown'},\n", + " {'code': '232\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " '233\\n'\n", + " 'robot_radius\\n'\n", + " ':\\n'\n", + " '0.3\\n'\n", + " '234\\n'\n", + " 'resolution\\n'\n", + " ':\\n'\n", + " '0.05',\n", + " 'context': 'For the global costmap, we have already set '\n", + " 'therobot_radiusparameter to create a circular footprint that '\n", + " 'matchessam_bot’s size and centered atbase_link. The parameter '\n", + " 'that was modified is shown in the code snippet below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'colcon\\n'\n", + " 'build\\n'\n", + " '.\\n'\n", + " 'install/setup.bash\\n'\n", + " 'ros2\\n'\n", + " 'launch\\n'\n", + " 'sam_bot_description\\n'\n", + " 'display.launch.py\\n',\n", + " 'context': 'First, we launchlaunch/display.launch.pyto launch the robot '\n", + " 'state publisher, spawnsam_botin Gazebo, and visualizesam_botand '\n", + " 'its footprint in Rviz. The robot state publisher publishes '\n", + " 'thebase_link=>sensorstransforms defined insam_bot’s URDF, while '\n", + " 'Gazebo’s differential drive plugin publishes '\n", + " 'theodom=>base_linktransform. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'base_link',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'run\\n'\n", + " 'tf2_ros\\n'\n", + " 'static_transform_publisher\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " '0\\n'\n", + " 'map\\n'\n", + " 'odom\\n',\n", + " 'context': 'Next, we will publish themap=>odomtransform using '\n", + " 'thestatic_transform_publisher. We publish themap=>odomtransform '\n", + " 'as static in this guide as a simple way to publish the transform '\n", + " 'and visualize the footprint. Open a new terminal and execute the '\n", + " 'lines below.',\n", + " 'filename': 'odom',\n", + " 'language': 'unknown'},\n", + " {'code': 'ros2\\n'\n", + " 'launch\\n'\n", + " 'nav2_bringup\\n'\n", + " 'navigation_launch.py\\n'\n", + " 'params_file:\\n'\n", + " '=\\n'\n", + " '\\n',\n", + " 'context': 'Lastly, we will launch Nav2 using '\n", + " 'thenav2_params.yamlconfiguration file we just made '\n", + " 'andnavigation_launch.py, the built-in launch file '\n", + " 'ofnav2_bringup. Open a new terminal and execute the following:',\n", + " 'filename': 'nav2_bringup',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Navigation Plugins\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Behavior-Tree Navigators\n", + "\n", + "\n", + "## Costmap Layers\n", + "\n", + "\n", + "## Costmap Filters\n", + "\n", + "\n", + "## Controllers\n", + "\n", + "\n", + "## Planners\n", + "\n", + "\n", + "## Smoothers\n", + "\n", + "\n", + "## Behaviors\n", + "\n", + "\n", + "## Waypoint Task Executors\n", + "\n", + "\n", + "## Goal Checkers\n", + "\n", + "\n", + "## Progress Checkers\n", + "\n", + "\n", + "## Behavior Tree Nodes\n", + "\n", + "\n", + "=== Document ===\n", + "Title: Constrained smoother\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Smoother Server Parameters\n", + "\n", + "\n", + "## Example\n", + "\n", + "\n", + "Code Blocks:\n", + "[{'code': 'smoother_server\\n'\n", + " ':\\n'\n", + " 'ros__parameters\\n'\n", + " ':\\n'\n", + " 'use_sim_time\\n'\n", + " ':\\n'\n", + " 'True\\n'\n", + " 'smoother_plugins\\n'\n", + " ':\\n'\n", + " '[\\n'\n", + " '\"SmoothPath\"\\n'\n", + " ']\\n'\n", + " 'SmoothPath\\n'\n", + " ':\\n'\n", + " 'plugin\\n'\n", + " ':\\n'\n", + " '\"nav2_constrained_smoother/ConstrainedSmoother\"\\n'\n", + " 'reversing_enabled\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to detect forward/reverse direction and cusps. Should be '\n", + " 'set to false for paths without orientations assigned\\n'\n", + " 'path_downsampling_factor\\n'\n", + " ':\\n'\n", + " '3\\n'\n", + " '# every n-th node of the path is taken. Useful for speed-up\\n'\n", + " 'path_upsampling_factor\\n'\n", + " ':\\n'\n", + " '1\\n'\n", + " '# 0 - path remains downsampled, 1 - path is upsampled back to '\n", + " 'original granularity using cubic bezier, 2... - more upsampling\\n'\n", + " 'keep_start_orientation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to prevent the start orientation from being smoothed\\n'\n", + " 'keep_goal_orientation\\n'\n", + " ':\\n'\n", + " 'true\\n'\n", + " '# whether to prevent the gpal orientation from being smoothed\\n'\n", + " 'minimum_turning_radius\\n'\n", + " ':\\n'\n", + " '0.40\\n'\n", + " '# minimum turning radius the robot can perform. Can be set to 0.0 '\n", + " '(or w_curve can be set to 0.0 with the same effect) for '\n", + " 'diff-drive/holonomic robots\\n'\n", + " 'w_curve\\n'\n", + " ':\\n'\n", + " '30.0\\n'\n", + " '# weight to enforce minimum_turning_radius\\n'\n", + " 'w_dist\\n'\n", + " ':\\n'\n", + " '0.0\\n'\n", + " '# weight to bind path to original as optional replacement for cost '\n", + " 'weight\\n'\n", + " 'w_smooth\\n'\n", + " ':\\n'\n", + " '2000000.0\\n'\n", + " '# weight to maximize smoothness of path\\n'\n", + " 'w_cost\\n'\n", + " ':\\n'\n", + " '0.015\\n'\n", + " '# weight to steer robot away from collision and cost\\n'\n", + " '# Parameters used to improve obstacle avoidance near cusps '\n", + " '(forward/reverse movement changes)\\n'\n", + " 'w_cost_cusp_multiplier\\n'\n", + " ':\\n'\n", + " '3.0\\n'\n", + " '# option to use higher weight during forward/reverse direction '\n", + " 'change which is often accompanied with dangerous rotations\\n'\n", + " 'cusp_zone_length\\n'\n", + " ':\\n'\n", + " '2.5\\n'\n", + " '# length of the section around cusp in which nodes use '\n", + " 'w_cost_cusp_multiplier (w_cost rises gradually inside the zone '\n", + " 'towards the cusp point, whose costmap weight eqals '\n", + " 'w_cost*w_cost_cusp_multiplier)\\n'\n", + " '# Points in robot frame to grab costmap values from. Format: [x1, '\n", + " 'y1, weight1, x2, y2, weight2, ...]\\n'\n", + " '# IMPORTANT: Requires much higher number of iterations to actually '\n", + " 'improve the path. Uncomment only if you really need it (highly '\n", + " 'elongated/asymmetric robots)\\n'\n", + " '# cost_check_points: [-0.185, 0.0, 1.0]\\n'\n", + " 'optimizer\\n'\n", + " ':\\n'\n", + " 'max_iterations\\n'\n", + " ':\\n'\n", + " '70\\n'\n", + " '# max iterations of smoother\\n'\n", + " 'debug_optimizer\\n'\n", + " ':\\n'\n", + " 'false\\n'\n", + " '# print debug info\\n'\n", + " 'gradient_tol\\n'\n", + " ':\\n'\n", + " '5e3\\n'\n", + " 'fn_tol\\n'\n", + " ':\\n'\n", + " '1.0e-15\\n'\n", + " 'param_tol\\n'\n", + " ':\\n'\n", + " '1.0e-20',\n", + " 'context': 'Parameter tolerance optimization termination criterion',\n", + " 'filename': 'DENSE_QR',\n", + " 'language': 'unknown'}]\n", + "\n", + "=== Document ===\n", + "Title: Writing a New Behavior Tree Plugin\n", + "\n", + "Tutorial Info:\n", + "{}\n", + "\n", + "Sections:\n", + "\n", + "## Overview\n", + "This tutorial shows how to create your own behavior tree (BT) plugin.\n", + "The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic.\n", + "\n", + "## Requirements\n", + "\n", + "\n", + "## Tutorial Steps\n", + "\n", + "\n", + "## 1- Creating a new BT Plugin\n", + "We will create a simple BT plugin node to perform an action on another server.\n", + "For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode.\n", + "Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes.\n", + "Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes.\n", + "The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode.\n", + "This action node can be considered as a reference for writing other action node plugins.\n", + "Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode.\n", + "The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients.\n", + "AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work.\n", + "When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode.\n", + "For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself.\n", + "TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor.\n", + "Let’s learn more about the methods needed to write a BT action plugin.\n", + "For this tutorial, we will only be using theon_tick()method.\n", + "In the constructor, we need to get any non-variable parameters that apply to the behavior tree node.\n", + "In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML.\n", + "Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node.\n", + "This will be seen later when we register this BT node as a plugin.\n", + "It also takes in the string name of the action server that it will call to execute some behavior.\n", + "Finally, a set of configurations that we can safely ignore for the purposes of most node plugins.\n", + "We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs.\n", + "TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal.\n", + "In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree.\n", + "It is set in thedurationparameter and inserted into thegoal_.\n", + "Thegoal_class variable is the goal that the ROS 2 action client will send to the action server.\n", + "So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request.\n", + "TheprovidedPorts()method gives us the opportunity to define input or output ports.\n", + "Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself.\n", + "For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery.\n", + "We set the type,int, the default1, the namewait_duration, and a description of the portWaittime.\n", + "Theon_tick()method is called when the behavior tree ticks a specific node.\n", + "For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked.\n", + "This is useful to keep metrics about the number of recoveries executed during a specific navigation run.\n", + "You could also log or update thegoal_waiting duration if that is a variable input.\n", + "The remaining methods are not used and are not mandatory to override them.\n", + "Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout.\n", + "The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden.\n", + "\n", + "## 2- Exporting the planner plugin\n", + "Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML.\n", + "Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them.\n", + "In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro.\n", + "In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names).\n", + "This lambda will return a unique pointer to the behavior tree node we have created.\n", + "Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments.\n", + "Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction.\n", + "We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin.\n", + "An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds.\n", + "\n", + "## 3- Add plugin library name to config\n", + "In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names.\n", + "\n", + "## 4- Run Your Custom plugin\n", + "Now you can use a behavior tree with your custom BT node.\n", + "For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below.\n", + "Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file.\n", + "\n", + "Code Blocks:\n", + "[{'code': 'WaitAction\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '(\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " ':\\n'\n", + " 'BtActionNode\\n'\n", + " '<\\n'\n", + " 'nav2_msgs\\n'\n", + " '::\\n'\n", + " 'action\\n'\n", + " '::\\n'\n", + " 'Wait\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'xml_tag_name\\n'\n", + " ',\\n'\n", + " 'action_name\\n'\n", + " ',\\n'\n", + " 'conf\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'int\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " 'getInput\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'if\\n'\n", + " '(\\n'\n", + " 'duration\\n'\n", + " '<=\\n'\n", + " '0\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'RCLCPP_WARN\\n'\n", + " '(\\n'\n", + " 'node_\\n'\n", + " '->\\n'\n", + " 'get_logger\\n'\n", + " '(),\\n'\n", + " '\"Wait duration is negative or zero \"\\n'\n", + " '\"(%i). Setting to positive.\"\\n'\n", + " ',\\n'\n", + " 'duration\\n'\n", + " ');\\n'\n", + " 'duration\\n'\n", + " '*=\\n'\n", + " '-1\\n'\n", + " ';\\n'\n", + " '}\\n'\n", + " 'goal_\\n'\n", + " '.\\n'\n", + " 'time\\n'\n", + " '.\\n'\n", + " 'sec\\n'\n", + " '=\\n'\n", + " 'duration\\n'\n", + " ';\\n'\n", + " '}',\n", + " 'context': 'In the constructor, we need to get any non-variable parameters '\n", + " 'that apply to the behavior tree node.\\n'\n", + " 'In this example, we need to get the value of the duration to '\n", + " 'sleep from the input port of the behavior tree XML.',\n", + " 'filename': 'on_tick()',\n", + " 'language': 'unknown'},\n", + " {'code': 'static\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'PortsList\\n'\n", + " 'providedPorts\\n'\n", + " '()\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'providedBasicPorts\\n'\n", + " '(\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'InputPort\\n'\n", + " '<\\n'\n", + " 'int\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"wait_duration\"\\n'\n", + " ',\\n'\n", + " '1\\n'\n", + " ',\\n'\n", + " '\"Wait time\"\\n'\n", + " ')\\n'\n", + " '});\\n'\n", + " '}',\n", + " 'context': 'TheprovidedPorts()method gives us the opportunity to define '\n", + " 'input or output ports.\\n'\n", + " 'Ports can be thought of as parameters that the behavior tree '\n", + " 'node has access to from the behavior tree itself.\\n'\n", + " 'For our example, there is only a single input port, '\n", + " 'thewait_durationwhich can be set in the BT XML for each instance '\n", + " 'of thewaitrecovery.\\n'\n", + " 'We set the type,int, the default1, the namewait_duration, and a '\n", + " 'description of the portWaittime.',\n", + " 'filename': 'Waittime',\n", + " 'language': 'unknown'},\n", + " {'code': 'void\\nWaitAction::on_tick\\n()\\n{\\nincrement_recovery_count\\n();\\n}',\n", + " 'context': 'Theon_tick()method is called when the behavior tree ticks a '\n", + " 'specific node.\\n'\n", + " 'For the wait BT node, we simply want to notify a counter on the '\n", + " 'blackboard that an action plugin that corresponds to a recovery '\n", + " 'was ticked.\\n'\n", + " 'This is useful to keep metrics about the number of recoveries '\n", + " 'executed during a specific navigation run.\\n'\n", + " 'You could also log or update thegoal_waiting duration if that is '\n", + " 'a variable input.',\n", + " 'filename': 'goal_',\n", + " 'language': 'unknown'},\n", + " {'code': 'BT_REGISTER_NODES\\n'\n", + " '(\\n'\n", + " 'factory\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeBuilder\\n'\n", + " 'builder\\n'\n", + " '=\\n'\n", + " '[](\\n'\n", + " 'const\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'string\\n'\n", + " '&\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " 'const\\n'\n", + " 'BT\\n'\n", + " '::\\n'\n", + " 'NodeConfiguration\\n'\n", + " '&\\n'\n", + " 'config\\n'\n", + " ')\\n'\n", + " '{\\n'\n", + " 'return\\n'\n", + " 'std\\n'\n", + " '::\\n'\n", + " 'make_unique\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " 'name\\n'\n", + " ',\\n'\n", + " '\"wait\"\\n'\n", + " ',\\n'\n", + " 'config\\n'\n", + " ');\\n'\n", + " '};\\n'\n", + " 'factory\\n'\n", + " '.\\n'\n", + " 'registerBuilder\\n'\n", + " '<\\n'\n", + " 'nav2_behavior_tree\\n'\n", + " '::\\n'\n", + " 'WaitAction\\n'\n", + " '>\\n'\n", + " '(\\n'\n", + " '\"Wait\"\\n'\n", + " ',\\n'\n", + " 'builder\\n'\n", + " ');\\n'\n", + " '}',\n", + " 'context': 'Now that we have created our custom BT node, we need to export '\n", + " 'our plugin so that it would be visible to the behavior tree when '\n", + " 'it loads a custom BT XML.\\n'\n", + " 'Plugins are loaded at runtime, and if they are not visible, then '\n", + " 'our BT Navigator server won’t be able to load them or use them.\\n'\n", + " 'In BehaviorTree.CPP, exporting and loading plugins is handled by '\n", + " 'theBT_REGISTER_NODESmacro.',\n", + " 'filename': 'BT_REGISTER_NODES',\n", + " 'language': 'unknown'},\n", + " {'code': '',\n", + " 'context': 'We finally give the builder to a factory to register.Waitgiven '\n", + " 'to the factory is the name in the behavior tree XML file that '\n", + " 'corresponds to this BT node plugin.\\n'\n", + " 'An example can be seen below, where theWaitBT XML node specifies '\n", + " 'a non-variable input portwait_durationof 5 seconds.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': 'bt_navigator:\\n'\n", + " ' ros__parameters:\\n'\n", + " ' use_sim_time: True\\n'\n", + " ' global_frame: map\\n'\n", + " ' robot_base_frame: base_link\\n'\n", + " ' odom_topic: /odom\\n'\n", + " ' default_bt_xml_filename: '\n", + " '\"navigate_w_replanning_and_recovery.xml\"\\n'\n", + " ' plugin_lib_names:\\n'\n", + " ' - nav2_back_up_action_bt_node # other plugin\\n'\n", + " ' - nav2_wait_action_bt_node # our new plugin\\n',\n", + " 'context': 'In order for the BT Navigator node to discover the plugin we’ve '\n", + " 'just registered, we need to list the plugin library name under '\n", + " 'the bt_navigator node in the configuration YAML file. '\n", + " 'Configuration should look similar to the one shown below. Take '\n", + " 'note of nav2_wait_action_bt_node listed under plugin_lib_names.',\n", + " 'filename': 'wait_duration',\n", + " 'language': 'unknown'},\n", + " {'code': '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '\\n'\n", + " '',\n", + " 'context': 'Select this BT XML file in your specific navigation request '\n", + " 'inNavigateToPoseor as the default behavior tree in the BT '\n", + " 'Navigator’s configuration yaml file.',\n", + " 'filename': 'NavigateToPose',\n", + " 'language': 'unknown'}]\n" + ] + } + ], + "source": [ + "import nest_asyncio\n", + "from pprint import pprint\n", + "nest_asyncio.apply()\n", + "\n", + "async def test_scraper():\n", + " extractor = DocumentationExtractor()\n", + " try:\n", + " docs = await extractor.extract_docs(\n", + " base_url=\"https://docs.nav2.org/\",\n", + " sections=[\"getting_started/index.html\"],\n", + " subdomain=\"nav2\", \n", + " version=\"latest\"\n", + " )\n", + " for doc in docs:\n", + " print(\"\\n=== Document ===\")\n", + " print(f\"Title: {doc['content']['title']}\")\n", + " print(\"\\nTutorial Info:\")\n", + " pprint(doc['content'].get('tutorial_info', {}))\n", + " print(\"\\nSections:\")\n", + " for section in doc['content']['sections']:\n", + " print(f\"\\n## {section['heading']}\")\n", + " print(section['content'])\n", + " if doc['content']['code_blocks']:\n", + " print(\"\\nCode Blocks:\")\n", + " pprint(doc['content']['code_blocks'])\n", + " finally:\n", + " await extractor.close()\n", + "\n", + "await test_scraper()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2024-12-06 14:50:25.362\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 759 links in section getting_started/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:25.520\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#configuring-nav2-costmap-2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:25.572\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#rpp-new-optional-interpolate-curvature-after-goal-behavior-and-fix-conflict-between-use-rotate-to-heading-and-allow-reversing\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:25.624\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#including-new-rotation-shim-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:25.792\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#why-use-a-dev-container\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:25.838\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#setup-your-environment-variables\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:25.881\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.032\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#install-stvl\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.083\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-nav2-loopback-simulator\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.127\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.351\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#common-sensor-messages\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.449\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#control-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.505\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#new-parameter-use-final-approach-orientation-for-the-3-2d-planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.549\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/RemovePassedGoals.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.595\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html#navigation2-architectural-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.642\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-bt-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.734\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#run-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.904\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/path_dist.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.953\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#new-costmap-layer\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:26.991\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.048\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/robots.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.091\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-navfn.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.137\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#help\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.236\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html#simple-smoother-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.375\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#the-costmap-activation-fails-when-required-transforms-are-not-available\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.420\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputePathThroughPoses.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.468\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#condition-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.521\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#behavior-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.615\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.672\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.718\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#velocity-smoother-applies-deceleration-when-timeout\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.896\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:27.952\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#introduction-of-costmapupdate-msg\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.072\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#other-pages-we-d-love-to-offer\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.126\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.208\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#prefer-forward-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.252\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.483\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#mppi-controller-addition-of-acceleration-constraints\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.528\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.573\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#general\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.629\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/collision_monitor/configuring-collision-detector-node.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.686\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#smacplanner2d-navfn-and-theta-fix-small-path-corner-cases\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.824\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-follow-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:28.951\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#costmap2d-ros-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.016\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.108\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#removed-global-map-topic-from-costmap-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.205\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.263\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#enable-keepout-filter\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.307\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.471\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#costmap-filter-info-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.514\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html#humble-roadmap\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.627\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#id1\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.680\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#caching-obstacle-heuristic-in-smac-planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.726\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#build-run-and-verification\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.780\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#driveonheading-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.823\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#profile-from-a-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:29.986\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.118\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/collision_monitor/configuring-collision-monitor-node.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.172\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#preparing-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.220\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.296\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.384\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.520\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#navigation-subtree\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.571\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#provided-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.616\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/denoise.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.715\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#costmap-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.761\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/obstacle_footprint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.818\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#footprint-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:30.868\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.048\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#run-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.091\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#option-to-limit-velocity-through-dwb-trajectory\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.188\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/voxel.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.294\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html#using-dev-containers\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.360\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.414\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#standard-time-units-in-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.584\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#robot-footprints\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.716\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#run-time-speed-up-of-smac-planner\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.765\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.811\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.871\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:31.941\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#setting-up-the-environment\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.141\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#fusing-vio-into-local-state-estimate\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.193\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.245\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.290\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.333\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-thetastar.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.427\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#fix-flickering-visualization\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.649\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#constraint-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.709\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#configuring-collision-monitor-with-velocitypolygon\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.750\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-thetastar.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.843\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#standardization-of-plugin-naming-with-double-colons\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.896\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#cancel-checker-interface-for-globalplanner\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:32.947\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.135\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/goal_dist.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.193\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#configuring-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.319\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#introduce-a-new-multi-robot-bringup-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.372\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#exporting-the-planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.429\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.492\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#mppi-acceleration\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.655\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/base_obstacle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.755\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#allow-multiple-goal-checkers-and-change-parameter-progress-checker-plugin-s-name-and-type\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.852\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.896\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html#smoother-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.936\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#licensing\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:33.982\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#ros-2\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.026\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/speed_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.446\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-btactionserver-btnavigator-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.570\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.727\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#prepare-filter-mask\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.775\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearCostmapAroundRobot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.837\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-cancel-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:34.944\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#action-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.017\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.228\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#fusing-vslam-into-global-state-estimate\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.319\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#obstacle-inflation-layer-and-path-following\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.418\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.465\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-nav2-bringup\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.506\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.581\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#id3\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.760\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.899\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.946\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#planner-plugin-selection\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:35.999\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#costmap-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.051\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#released-distribution-binaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.109\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#default-behavior-tree-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.321\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsStopped.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.366\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_through_poses_recovery.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.410\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#security\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.460\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.507\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#lifecycle-nodes-and-bond\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.553\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.638\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldAControllerRecoveryHelp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.833\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#pass-the-plugin-name-through-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.894\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:36.948\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-navfn.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.013\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.134\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.340\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#selection-of-behavior-tree-in-each-navigation-action\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.427\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#building-a-development-image\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.507\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#changes-to-map-yaml-file-path-for-map-server-node-in-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.609\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#prediction-horizon-costmap-sizing-and-offsets\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.720\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#recursive-refinement-of-smac-and-simple-smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.898\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#adding-gazebo-plugins-to-a-urdf\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:37.967\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#setting-up-zed-ros\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:38.072\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#preliminaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:38.189\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:38.482\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:38.551\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#run-nav2-stack\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:38.633\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:38.735\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#simplechargingdock-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.011\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#configure-costmap-filter-info-publisher-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.080\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#costmaps-and-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.143\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#profile-from-a-launch-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.207\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#getting-started\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.268\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#twiststamped-default-cmdvel-change\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.541\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.629\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#setup-gazebo-world\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.684\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#familiarization-with-the-smoother-bt-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.768\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#robot-footprint-vs-radius\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:39.965\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#isbatterychargingcondition-bt-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:40.100\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#allow-behavior-server-plugins-to-access-the-action-result\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:40.256\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:40.579\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#rotate-in-place-behavior\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:40.933\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.063\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/smac/configuring-smac-hybrid.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.264\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#lifecycle-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.326\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.555\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.603\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/TruncatePath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.664\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#odometry\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.815\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#general-words-of-wisdom\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:41.882\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#action-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.071\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#smac-planner-hybrid-a-new-features\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.136\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html#iron-roadmap\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.190\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#build-instructions\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.339\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-handler\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.414\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#waypoint-following\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.601\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.684\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.837\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:42.905\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#groot-support\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.185\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#publish-collision-monitor-state\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.273\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.356\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ControllerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.649\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#from-nav2-bringup\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.709\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/DockRobot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.765\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.830\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#assistedteleop-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.899\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#smacplanner2d-and-theta-fix-goal-orientation-being-ignored\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:43.995\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearCostmapExceptRegion.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.167\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#opennav-coverage-project\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.230\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#error-codes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.297\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#visualize-behavior-trees\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.385\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#removed-use-approach-velocity-scaling-param-in-rpp\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.516\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#subtrees-obtain-shared-resources\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.695\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-collision-monitor.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.771\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#added-smoother-task-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.839\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#poseprogresschecker-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.904\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#dropping-support-for-live-groot-monitoring-of-nav2\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:44.970\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-thetastar.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.072\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/RateController.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.219\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#writing-the-urdf\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.283\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.411\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.496\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#notes-to-users\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.556\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.712\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#what-why-how\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.773\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#exploring-your-first-container\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.882\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/InitialPoseReceived.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.932\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#constrained-smoother\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:45.981\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-pipelinesequence\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.021\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#enable-denoise-layer\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.072\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#refactored-amcl-motion-models-as-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.303\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/odometry_calibration.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.363\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.406\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/DriveOnHeading.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.452\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#behaviors\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.503\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.643\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smacplannerhybrid-viz-expansions-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.799\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#simple-commander-python-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.855\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputePathToPose.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.906\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#dwb-forward-vs-reverse-pruning\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.948\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/wait_at_waypoint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:46.989\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.085\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.134\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.288\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.340\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#costmap2d-and-stvl\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.386\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.430\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/DistanceTraveled.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.541\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.597\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-rviz-plugin-for-selecting-planners-controllers-goal-checkers-progress-checkers-and-smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.649\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Smooth.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.810\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.879\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#creating-a-new-planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:47.980\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#interpreting-results\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.064\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#ackermann-motion-model\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.125\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#dynamic-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.183\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#recovery-to-behavior\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.397\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#load-save-and-loop-waypoints-from-the-nav2-panel-in-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.455\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#setup-navigation-system\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.503\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#testing-it-out\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.541\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/SingleTrigger.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.585\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/TruncatePathLocal.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.636\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.741\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#fix-costmaplayer-cleararea-invert-param-logic\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.870\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#followpath-goal-checker-id-attribute\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.923\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#behaviortree-cpp-upgraded-to-version-4-5\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:48.999\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:49.201\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#putting-it-all-together\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:51.531\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#visualizations-from-docker\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:51.602\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#regulatedpurepursuitcontroller\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:51.647\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#working-with-slam\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:51.692\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#inflation-potential-fields\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:51.838\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#simulating-sensors-using-gazebo\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.009\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/build_troubleshooting_guide.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.071\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#setup-rviz-clicked-point\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.118\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.162\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/static.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.270\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.313\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/SpeedController.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.362\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.548\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.649\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#launch-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.690\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#what-is-a-dev-container\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#smac-planner-on-approach-to-goal-shortcutting-solutions\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:52.869\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#adding-gazebo-plugins-to-a-urdf\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.056\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#what-is-the-rotation-shim-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.107\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html#savitzky-golay-smoother-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.157\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#revamped-multirobot-bringup-and-config-files-to-use-namespaces\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.265\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.316\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/obstacle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.363\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.425\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.620\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.683\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#exporting-the-navigator-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.727\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#launch-turtlebot-3\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.780\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#recovery-action-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.818\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:53.913\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#added-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.099\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#getting-started-simplification\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.143\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ReinitializeGlobalLocalization.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.190\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.248\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.291\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-rviz-tool-for-costmap-cost-cell-inspection\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.382\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.434\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#pass-the-plugin-name-through-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.620\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldAPlannerRecoveryHelp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.664\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#how-it-works\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.722\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.815\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/BackUp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.858\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.906\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/RemoveInCollisionGoals.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:54.962\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.159\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#added-twiststamped-option-for-commands\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.263\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.336\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.386\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#specifying-a-smoother-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.443\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#changes-to-mppi-path-angle-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.670\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/UndockRobot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.832\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#rotation-shim-controller-new-parameter-rotate-to-goal-heading\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.884\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.928\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:55.971\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#configuring-rotation-shim-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.030\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#launch-nav2\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.195\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.286\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#preliminaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.325\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearEntireCostmap.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.366\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelSpin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.415\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#controllers\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.462\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#setting-up-the-zed-x-camera\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.508\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.609\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/AssistedTeleop.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.738\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.791\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#collision-monitor-added-watchdog-mechanism-based-on-source-timeout-parameter-with-default-blocking-behavior\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.842\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#removed-kinematic-limiting-in-rpp\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:56.886\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#how-do-dev-containers-work\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.002\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#configuring-robot-localization\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.047\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.089\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/keepout_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.267\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-pathlongeronapproach-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.398\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.465\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#replanning-at-a-constant-rate-and-if-the-path-is-invalid\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.509\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/kinematic.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.556\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#automatic-backtrace-on-crash\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.596\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#id1\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.848\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#spawning-the-robot-in-gazebo\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.895\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#send-a-goal-pose\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.939\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelControl.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:57.981\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#provided-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.032\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#change-duration-type-in-wait-action-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.083\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.183\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#collision-monitor-dynamic-radius-for-circle-type-polygons\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.308\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#behavior-tree-navigators\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.347\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.400\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#btactionserver-use-native-library-halttree\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.451\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#run-straightline-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.543\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.581\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html#description\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.629\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.828\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-a-launch-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.871\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/prefer_forward.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:58.993\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-amcl.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.046\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#expose-action-server-s-result-timeout\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.087\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/photo_at_waypoint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.129\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/integrating_vio.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.349\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#nav2-controllers-and-goal-checker-plugin-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.479\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#lifecycle-node-added-bond-heartbeat-period-parameter-and-allow-disabling-the-bond-mechanism\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.534\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#simple-python-commander\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.578\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#build\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.653\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#costmap-2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.692\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-robot-interfaces\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.948\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:50:59.970\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/rviz-set-initial-pose.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.010\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelDriveOnHeading.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.062\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#recovery-subtree\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.102\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.152\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navigatethroughposes-and-computepaththroughposes-actions-added\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.243\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#decorator-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.398\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.494\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#selecting-the-algorithm-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.536\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/GetPoseFromPath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.598\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#computepathtopose-bt-node-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.739\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#simulating-an-odometry-system-using-gazebo\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:00.949\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.000\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.082\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#mppi-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.127\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#create-the-behavior-tree\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.230\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.272\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#for-jazzy-and-newer\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.443\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.492\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.565\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.676\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#nav2-rviz-panel-action-feedback-information\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.722\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.772\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#sensor-msgs-pointcloud-to-sensor-msgs-pointcloud2-change\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:01.962\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.018\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.127\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.167\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelCoverage.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.209\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.254\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#costmap-2d-node-default-constructor\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.302\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#feedback-for-navigation-failures\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.562\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#spin-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.612\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#ray-tracing-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.658\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#state-estimation\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.712\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html#regulated-pure-pursuit-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.767\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#simple-commander-api-allows-multi-robot-namespacing\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:02.863\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.020\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.065\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.135\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#setting-up-odometry-on-your-robot\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.179\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#savitzky-golay-smoother\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.273\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#standards\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.312\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/controls/RoundRobin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.356\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.566\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.634\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.738\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.789\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#controllerserver-new-parameter-failure-tolerance\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.845\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navigatetopose-action-feedback-updates\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:03.887\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#give-behavior-server-access-to-both-costmaps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.075\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/smac/configuring-smac-2d.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.197\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.241\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.286\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#expanded-planner-benchmark-tests\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.327\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/PlannerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.368\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputeCoveragePath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.450\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.593\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#composition\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.658\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#added-assisted-teleop\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.725\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#regulatedpurepursuit-controller-rpp-new-parameter-use-cancel-deceleration\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.772\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/rotate_to_goal.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.812\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#planner-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.913\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#euclidean-distance-2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:04.953\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelBackUp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.136\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#for-docker-based-development\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.190\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-navigator-groot-multiple-navigators\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.325\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#cost-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.376\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsStuck.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.451\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.654\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.752\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:05.919\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#visualizing-footprint-in-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.002\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html#new-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.227\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#move-error-code-enumerations\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.335\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#obstacles-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.475\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#substitution-in-parameter-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.706\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#respawn-support-in-launch-and-lifecycle-manager\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.805\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/SmootherSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.884\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:06.989\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.070\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.315\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#navigate-to-pose-with-replanning-and-recovery\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.393\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-action-nodes-exception-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.479\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/rviz_initial.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.549\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.802\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#build-run-and-verification\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:07.939\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#run-gradientlayer-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.006\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.412\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.499\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#visualization-using-rviz\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.632\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#add-velocitypolygon-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.809\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.876\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html#graceful-controller-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:08.946\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.032\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#for-iron-and-older\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.107\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smac-planner-start-pose-included-in-path\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.399\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#navigation-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.497\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#goal-checkers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.575\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-slam\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.657\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#rewrittenyaml-could-add-new-parameters-to-yamls\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:09.872\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-navfn.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.023\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#pass-the-plugin-name-through-the-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.077\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html#rotation-shim-controller-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.175\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.374\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.535\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#run-pure-pursuit-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.630\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#mapping-and-localization\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.696\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#add-plugin-library-name-to-config\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.887\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-collision-monitor.html#provided-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:10.966\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-behavior-tree-navigator-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:11.091\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#changes-to-mppi-goal-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:11.170\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#id2\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:11.447\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#gps-localization-overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:11.551\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#creating-a-new-behavior-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:11.740\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#goal-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.033\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#controllers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.097\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.269\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#odometry-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.525\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldASmootherRecoveryHelp.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.656\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.717\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html#provided-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:12.791\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#nav2-deployment-image\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.023\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#new-clearcostmapexceptregion-and-clearcostmaparoundrobot-bt-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.164\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#global-frame-removed-from-2-bt-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.215\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/GoalCheckerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.276\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#trajectory-critics\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.340\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-option-for-the-voxel-and-obstacle-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.527\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-graceful-cancellation-api-for-controllers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.677\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#smac-planner-debug-param-name-change\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.741\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#new-behavior-tree-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:13.818\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#behavior-trees\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:14.109\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#nav2-launch-options\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:14.578\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/NavigateToPose.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:14.730\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html#conclusion\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:14.818\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#option-to-disable-zero-velocity-publishing-on-goal-exit\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:14.897\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#modify-navigation2-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.118\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#costmap-filters-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.226\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#docking-action-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.333\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.385\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_and_pause_near_goal_obstacle.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.445\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/roadmap/roadmap.html#jazzy-roadmap\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.625\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/binary_filter.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.693\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/twirling.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.773\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:15.907\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#export-and-make-gradientlayer-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.163\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/navigate-to-pose.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.251\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.331\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#full-stack-uses-node-clocks\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.411\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.562\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html#creating-dev-containers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.675\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/GoalUpdater.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.771\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#planner-and-controller-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.851\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#change-and-fix-behavior-of-dynamic-parameter-change-detection\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.922\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:16.970\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/path_align.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.247\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.325\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GoalReached.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.397\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#environmental-representation\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.464\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#chargingdock-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.531\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#enable-the-plugin-in-costmap2d\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.803\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#replanning-only-if-path-is-invalid\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.915\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#modifying-your-bt-xml\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:17.981\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#major-improvements-to-smac-planners\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.051\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelAssistedTeleop.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.250\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.372\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/navstack-ready.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.565\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/index.html#id1\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.762\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#static-layer-new-parameter-footprint-clearing-enabled\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.822\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#thetastarplanner\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.894\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#demo-execution\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:18.952\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.042\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navfn-planner-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.094\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#goal-checker-api-changed\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.269\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/controls/RecoveryNode.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.328\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.370\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#docker-container-images\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.467\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-plugins/standard_traj_generator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.514\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.556\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.600\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smac-planner-path-tolerances\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.792\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#initialize-the-location-of-turtlebot-3\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.837\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#transforms-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:19.977\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#exporting-the-planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.036\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-a-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.090\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#map-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.136\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#behavior-tree-uses-error-codes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.325\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#costmap2d-current-usage\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.453\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#run-behavior-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.502\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#write-a-new-costmap2d-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.557\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#understanding-ros-docker-images\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.656\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#adding-physical-properties\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.916\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#create-a-new-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:20.967\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#more-stable-regulation-on-curves-for-long-lookahead-distances\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.011\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Wait.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.067\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#for-docker-based-deployment\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.139\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-plugins/limited_accel_generator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.253\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#introduction-of-soft-real-time-action-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.389\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#api-change-for-nav2-core\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.473\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.538\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#new-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.594\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#launch-navigation2\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.693\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#computepathtopose-action-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.880\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/DistanceController.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:21.945\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#behaviors\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.009\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#extending-the-btservicenode-to-process-service-results\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.065\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#decorator-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.164\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#smacplanner\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.208\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_with_consistent_replanning_and_if_path_becomes_invalid.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.419\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.480\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-safety-behavior-model-limit-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.526\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.650\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.701\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.757\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#plugin-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:22.948\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#costmap2d-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.006\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#exporting-the-controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.116\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#nav2-academic-overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.162\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#rolling-development-source\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.215\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#exporting-the-behavior-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.273\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.522\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/smac/configuring-smac-lattice.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.664\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.722\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.773\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#added-optional-collision-checking-for-the-docking-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.817\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/FollowPath.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:23.982\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/pose_progress_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.021\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/related_projects.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.118\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-model-predictive-path-integral-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.162\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/PathExpiringTimer.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.206\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.257\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#recovery-behavior-timeout\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.309\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#change-polygon-points-parameter-format-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.582\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.665\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#adding-docking-server-to-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.748\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#velocity-deadband-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#new-rviz-panel-for-docking\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:24.896\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#footprint-collision-checker-api\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.035\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/about/index.html#contact\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.091\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.135\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.178\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/TimeExpired.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.276\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#new-nav2-velocity-smoother\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.320\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tuning/index.html#controller-plugin-selection\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.371\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#addition-of-new-mppi-cost-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.568\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#waypoint-task-executors\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.617\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#backup-recovery-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.736\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#important-docker-commands\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.776\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/NavigateThroughPoses.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.834\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#appendix\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:25.890\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.124\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#id4\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.274\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.334\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.378\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#preliminaries\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.494\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#build-run-and-verification\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.628\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_profile.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.674\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.720\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#smootherselector-bt-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.779\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-amcl.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.817\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/goal_align.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.932\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:26.984\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#prerequisites\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.155\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#developer-certification-of-origin-dco\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.196\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ProgressCheckerSelector.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.243\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Spin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.377\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#launch-and-build-files\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.460\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#goal-angle-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.500\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/simple_goal_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.673\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.782\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/commander_api/index.html#examples-and-demos\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.837\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#run-dynamic-object-following-in-nav2-simulation\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.890\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#reduce-nodes-and-executors\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.943\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#server-updates\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:27.983\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#new-particle-filter-messages\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.081\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#changes-to-mppi-path-handling-for-directionality\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.201\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#run-your-custom-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.252\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#map-server-re-work\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.289\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsBatteryLow.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.332\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#publish-costmap-layers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.459\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#logged-gps-waypoint-follower-waypoint-logging\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.503\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/gazebo_turtlebot1.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.709\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html#velocity-smoother-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.771\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/iterator.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.825\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#backup-bt-node-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:28.884\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-node-in-nav2-collision-monitor-collision-detector\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.006\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#prepare-filter-mask\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.064\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.269\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#trajectory-visualization\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.315\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/trajectory_critics/oscillation.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.331\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/rviz-not-started.png: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.445\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#behavior-tree-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.495\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/input_at_waypoint.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.550\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#setup-gps-localization-system\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.605\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#configuring-docking-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.754\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsPathValid.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.800\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#from-large-project\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.915\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/docker_dev.html#nav2-development-image\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:29.984\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#build-and-launch\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.070\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#new-denoise-costmap-layer-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.135\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#urdf-and-the-robot-state-publisher\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.337\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#renamed-ros-parameter-in-collision-monitor\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.392\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#smoothers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.434\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#install\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.481\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/camera_calibration.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.545\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.645\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.819\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#pass-the-plugin-name-through-the-params-file\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.860\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html#process\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.900\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/AreErrorCodesPresent.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:30.943\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#controller-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.032\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#followpoint-capability\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.101\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#launch-and-build-files\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.147\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.331\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/build_docs/index.html#generate-doxygen\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.370\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.487\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.539\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#dynamic-composition\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.582\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#new-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.633\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#use-interpolation-rpp-parameter-depreciated\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.673\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/PathLongerOnApproach.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:31.851\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/simple_progress_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.005\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html#bt-truncatepathlocal-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.059\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Galactic.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.113\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.161\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_smoother.html#requirements\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.201\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/dwb-params/visualization.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.447\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#costmap-filters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.501\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#plugin-libraries-in-bt-navigator-only-includes-custom-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.568\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.615\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.669\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#default-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.778\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#condition-nodes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.913\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.954\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsBatteryCharging.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:32.996\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#global-positioning-localization-and-slam\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.050\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-graceful-motion-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.148\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.200\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#enable-speed-filter\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.246\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-recovery\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.427\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/TransformAvailable.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.473\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_recovery.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.518\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-map-server.html#map-saver-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.634\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.682\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.731\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-navigation2\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#configuring-primary-controller\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:33.959\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#removed-use-sim-time-from-yaml\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.101\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#robot-localization-demo\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.145\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Dashing.html#new-packages\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.203\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#run-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.241\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.297\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-amcl.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.563\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/odom/setup_odom.html#setup-and-prerequisites\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.604\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.656\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#dynamic-enabling-disabling-of-sources-polygons-in-collision-monitor-detector\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.700\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#simplified-costmap2dros-constructors\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.802\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:34.839\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/controls/PipelineSequence.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.000\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/inflation.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.065\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#default-plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.104\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.156\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#opennav-docking-project\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.250\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#parameterizable-collision-checking-in-rpp\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.310\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#dock-database\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.362\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#prerequisites\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.555\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#demo-execution\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.710\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-angle-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.758\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-roundrobin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.819\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#added-gps-waypoint-follower-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:35.860\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#tutorial-steps\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.323\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/navigation_with_recovery_behaviours.gif: 'utf-8' codec can't decode byte 0xf7 in position 10: invalid start byte\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.407\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#create-a-new-navigator-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.645\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/costmap-plugins/range.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.688\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#edit-behavior-trees\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.728\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GloballyUpdatedGoal.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.812\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#twirling-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.869\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html#example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:36.974\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#static-transform-publisher-demo\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.104\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#transforms-in-navigation2\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.152\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_groot.html#adding-a-custom-node\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.191\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/development_guides/involvement_docs/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.240\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#other-forms\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.345\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/using_docking.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.427\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-align-critic\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.626\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html#behavior-server-error-codes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.680\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#planner-controller-smoother-and-recovery-servers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.733\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Iron.html#new-collision-monitor-parameter\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.848\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/concepts/index.html#action-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.887\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GoalUpdated.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.938\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#navigatetopose-bt-node-interface-changes\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:37.984\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Jazzy.html#docking-with-static-infrastructure-or-dynamic-docking\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.153\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Humble.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.257\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelWait.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.303\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/get_backtrace.html#overview\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.358\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#configure-costmap-filter-info-publisher-server\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.399\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/behavior_trees/trees/follow_point.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.440\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.484\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#setup\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.743\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#obstacle-marking-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.794\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Foxy.html#removed-bt-xml-launch-configurations\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.850\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#interactive-gps-waypoint-follower\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:38.923\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#sensor-introduction\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.029\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#backup-behavior-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.195\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/stopped_goal_checker.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.255\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#configuring-the-robot-s-footprint\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.316\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#progress-checkers\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.371\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html#smoother-server-parameters\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.469\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#creating-a-new-bt-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.512\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 754 links in section development_guides/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.718\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/getting_started/index.html#running-the-example\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.781\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/getting_started/index.html#installation\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:39.880\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/getting_started/index.html#navigating\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:40.080\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/getting_started/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:40.354\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 734 links in section concepts/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:40.413\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/migration/Eloquent.html#eloquent-migration\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:40.460\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 755 links in section setup_guides/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:40.597\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/index.html#configuration\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:41.457\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 754 links in section tutorials/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:44.006\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 754 links in section plugin_tutorials/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:45.053\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 754 links in section configuration/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.279\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 752 links in section tuning/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.457\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html#configuring-rotation-shim\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.631\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/index.html#setup-guides\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.695\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugins/index.html#plugins\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.749\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#writing-new-nav2controller-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.792\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#select-algorithm\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.900\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m187\u001b[0m - \u001b[1mProcessed: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#writing-new-nav2planner-plugin\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:48.963\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 754 links in section behavior_trees/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:49.356\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m157\u001b[0m - \u001b[1mFound 750 links in section commander_api/index.html\u001b[0m\n", + "\u001b[32m2024-12-06 14:51:53.628\u001b[0m | \u001b[31m\u001b[1mERROR \u001b[0m | \u001b[36mdoc_extract\u001b[0m:\u001b[36m_get_page_content\u001b[0m:\u001b[36m29\u001b[0m - \u001b[31m\u001b[1mError fetching https://docs.nav2.org/_images/readme.gif: 'utf-8' codec can't decode byte 0xcc in position 8: invalid continuation byte\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 774 documents to exported_docs/nav2\n" + ] + } + ], + "source": [ + "import nest_asyncio\n", + "import os\n", + "import json\n", + "from pathlib import Path\n", + "from pprint import pprint\n", + "nest_asyncio.apply()\n", + "\n", + "async def test_scraper():\n", + " sections = [\n", + " \"getting_started/index.html\",\n", + " \"development_guides/index.html\", \n", + " \"concepts/index.html\",\n", + " \"setup_guides/index.html\",\n", + " \"tutorials/index.html\",\n", + " \"plugin_tutorials/index.html\",\n", + " \"configuration/index.html\",\n", + " \"tuning/index.html\",\n", + " \"behavior_trees/index.html\",\n", + " \"commander_api/index.html\"\n", + " ]\n", + " output_dir = Path(\"exported_docs/nav2\")\n", + " output_dir.mkdir(parents=True, exist_ok=True)\n", + " \n", + " extractor = DocumentationExtractor()\n", + " try:\n", + " docs = await extractor.extract_docs(\n", + " base_url=\"https://docs.nav2.org/\",\n", + " sections=sections,\n", + " subdomain=\"nav2\",\n", + " version=\"latest\"\n", + " )\n", + " for doc in docs:\n", + " filename = f\"{doc['content']['title'].replace('/', '_')}.txt\"\n", + " filepath = output_dir / filename\n", + " \n", + " with open(filepath, 'w') as f:\n", + " f.write(f\"Title: {doc['content']['title']}\\n\")\n", + " f.write(f\"URL: {doc['source']['url']}\\n\")\n", + " f.write(f\"Section: {doc['metadata']['section']}\\n\")\n", + " f.write(\"-\" * 80 + \"\\n\\n\")\n", + " \n", + " if tutorial_info := doc['content'].get('tutorial_info'):\n", + " f.write(\"Tutorial Info:\\n\")\n", + " f.write(json.dumps(tutorial_info, indent=2) + \"\\n\\n\")\n", + " \n", + " for section in doc['content']['sections']:\n", + " f.write(f\"\\n## {section['heading']}\\n\")\n", + " f.write(section['content'] + \"\\n\")\n", + " \n", + " if doc['content']['code_blocks']:\n", + " f.write(\"\\nCode Examples:\\n\")\n", + " for block in doc['content']['code_blocks']:\n", + " f.write(f\"\\nLanguage: {block['language']}\\n\")\n", + " if block['filename']:\n", + " f.write(f\"File: {block['filename']}\\n\")\n", + " f.write(\"```\\n\")\n", + " f.write(block['code'] + \"\\n\")\n", + " f.write(\"```\\n\")\n", + " \n", + " print(f\"Saved {len(docs)} documents to {output_dir}\")\n", + " finally:\n", + " await extractor.close()\n", + "\n", + "await test_scraper()" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2024-12-06 15:13:07.569\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://moveit.picknik.ai/main/doc/tutorials/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:07.570\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 7 links in section doc/tutorials/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:07.785\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://moveit.picknik.ai/main/doc/examples/examples.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:07.786\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 36 links in section doc/examples/examples.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:09.203\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://moveit.picknik.ai/main/doc/concepts/concepts.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:09.203\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 7 links in section doc/concepts/concepts.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:09.421\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://moveit.picknik.ai/main/doc/how_to_guides/how_to_guides.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:13:09.423\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 18 links in section doc/how_to_guides/how_to_guides.html\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 4 MoveIt2 documents to exported_docs/moveit2\n" + ] + } + ], + "source": [ + "import nest_asyncio\n", + "import os\n", + "import json\n", + "from pathlib import Path\n", + "from pprint import pprint\n", + "nest_asyncio.apply()\n", + "\n", + "async def test_scraper():\n", + " sections = [\n", + " # \"index.html\",\n", + " \"doc/tutorials/tutorials.html\",\n", + " \"doc/examples/examples.html\", \n", + " \"doc/concepts/concepts.html\",\n", + " \"doc/how_to_guides/how_to_guides.html\"\n", + " ]\n", + " output_dir = Path(\"exported_docs/moveit2\")\n", + " output_dir.mkdir(parents=True, exist_ok=True)\n", + " \n", + " extractor = DocumentationExtractor()\n", + " try:\n", + " docs = await extractor.extract_docs(\n", + " base_url=\"https://moveit.picknik.ai/main/\",\n", + " sections=sections,\n", + " subdomain=\"moveit2\",\n", + " version=\"main\"\n", + " )\n", + " for doc in docs:\n", + " filename = f\"{doc['content']['title'].replace('/', '_')}.txt\"\n", + " filepath = output_dir / filename\n", + " \n", + " with open(filepath, 'w') as f:\n", + " f.write(f\"Title: {doc['content']['title']}\\n\")\n", + " f.write(f\"URL: {doc['source']['url']}\\n\")\n", + " f.write(f\"Section: {doc['metadata']['section']}\\n\")\n", + " f.write(\"-\" * 80 + \"\\n\\n\")\n", + " \n", + " if tutorial_info := doc['content'].get('tutorial_info'):\n", + " f.write(\"Tutorial Info:\\n\")\n", + " f.write(json.dumps(tutorial_info, indent=2) + \"\\n\\n\")\n", + " \n", + " for section in doc['content']['sections']:\n", + " f.write(f\"\\n## {section['heading']}\\n\")\n", + " f.write(section['content'] + \"\\n\")\n", + " \n", + " if doc['content']['code_blocks']:\n", + " f.write(\"\\nCode Examples:\\n\")\n", + " for block in doc['content']['code_blocks']:\n", + " f.write(f\"\\nLanguage: {block['language']}\\n\")\n", + " if block['filename']:\n", + " f.write(f\"File: {block['filename']}\\n\")\n", + " f.write(\"```\\n\")\n", + " f.write(block['code'] + \"\\n\")\n", + " f.write(\"```\\n\")\n", + " \n", + " print(f\"Saved {len(docs)} MoveIt2 documents to {output_dir}\")\n", + " finally:\n", + " await extractor.close()\n", + "\n", + "await test_scraper()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2024-12-06 15:39:59.239\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/getstarted\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.242\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 18 links in section getstarted\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.291\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/harmonic/install_osx\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.343\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/citadel/install_osx\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.383\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/libs\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.433\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/citadel/install_ubuntu\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.468\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/citadel/install\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.513\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/fortress/install_ubuntu\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.562\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/garden/install_osx\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.750\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/garden/install\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.788\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/garden/install_ubuntu\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.907\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/fortress/install_osx\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.944\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/harmonic/install\u001b[0m\n", + "\u001b[32m2024-12-06 15:39:59.982\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/citadel/tutorials\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.040\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/ionic/install_ubuntu\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.096\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/fortress/install\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.278\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/ionic/install\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.321\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/docs/harmonic/install_ubuntu\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.354\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/tutorials\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.356\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 30 links in section tutorials\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.365\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/tools/2/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.402\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/common/5/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.432\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/plugin/2/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.455\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/transport/13/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.464\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/sensors/8/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.484\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/launch/7/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.492\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/msgs/10/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.526\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/utils/2/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.536\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/rendering/8/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.552\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/fuel_tools/9/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.564\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/cmake/3/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.596\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/math/7/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.792\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/physics/7/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.809\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/sim/8/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.819\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m255\u001b[0m - \u001b[1mProcessed sub-page: https://gazebosim.org/api/gui/8/tutorials.html\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.875\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/building_robot\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.878\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 2 links in section building_robot\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.926\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/moving_robot\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.928\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 2 links in section moving_robot\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.992\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/sdf_worlds\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:00.994\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 3 links in section sdf_worlds\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.119\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/sensors\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.122\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 3 links in section sensors\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.334\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/actors\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.335\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 0 links in section actors\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.401\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/gui\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.403\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 3 links in section gui\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.471\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/manipulating_models\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.472\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 3 links in section manipulating_models\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.533\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/ros2_overview\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.534\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 1 links in section ros2_overview\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.601\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/ros_installation\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.603\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 4 links in section ros_installation\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.668\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m239\u001b[0m - \u001b[1mProcessed section page: https://gazebosim.org/docs/latest/architecture\u001b[0m\n", + "\u001b[32m2024-12-06 15:40:01.669\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mextract.doc_extract\u001b[0m:\u001b[36mextract_docs\u001b[0m:\u001b[36m243\u001b[0m - \u001b[1mFound 0 links in section architecture\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved 43 Gazebo documents to exported_docs/gazebo\n" + ] + } + ], + "source": [ + "async def test_scraper_and_save():\n", + " sections = [\n", + " \"getstarted\",\n", + " \"tutorials\",\n", + " \"building_robot\",\n", + " \"moving_robot\",\n", + " \"sdf_worlds\",\n", + " \"sensors\",\n", + " \"actors\",\n", + " \"gui\",\n", + " \"manipulating_models\",\n", + " \"ros2_overview\",\n", + " \"ros_installation\", \n", + " \"architecture\"\n", + " ]\n", + " \n", + " output_dir = Path(\"exported_docs/gazebo\")\n", + " output_dir.mkdir(parents=True, exist_ok=True)\n", + " \n", + " extractor = DocumentationExtractor()\n", + " try:\n", + " docs = await extractor.extract_docs(\n", + " base_url=\"https://gazebosim.org/docs/latest\",\n", + " sections=sections,\n", + " subdomain=\"gazebo\",\n", + " version=\"latest\"\n", + " )\n", + " \n", + " for doc in docs:\n", + " filename = f\"{doc['content']['title'].replace('/', '_')}.txt\"\n", + " filepath = output_dir / filename\n", + " \n", + " with open(filepath, 'w', encoding='utf-8') as f:\n", + " f.write(f\"Title: {doc['content']['title']}\\n\")\n", + " f.write(f\"URL: {doc['source']['url']}\\n\")\n", + " f.write(f\"Section: {doc['metadata']['section']}\\n\")\n", + " f.write(\"-\" * 80 + \"\\n\\n\")\n", + " \n", + " if tutorial_info := doc['content'].get('tutorial_info'):\n", + " f.write(\"Tutorial Info:\\n\")\n", + " f.write(json.dumps(tutorial_info, indent=2) + \"\\n\\n\")\n", + " \n", + " for section in doc['content']['sections']:\n", + " f.write(f\"\\n## {section['heading']}\\n\")\n", + " f.write(section['content'] + \"\\n\")\n", + " \n", + " if doc['content']['code_blocks']:\n", + " f.write(\"\\nCode Examples:\\n\")\n", + " for block in doc['content']['code_blocks']:\n", + " f.write(f\"\\nLanguage: {block['language']}\\n\")\n", + " if block['filename']:\n", + " f.write(f\"File: {block['filename']}\\n\")\n", + " f.write(\"```\\n\")\n", + " f.write(block['code'] + \"\\n\")\n", + " f.write(\"```\\n\")\n", + " \n", + " print(f\"Saved {len(docs)} Gazebo documents to {output_dir}\")\n", + " finally:\n", + " await extractor.close()\n", + "\n", + "if __name__ == \"__main__\":\n", + " import asyncio\n", + " asyncio.run(test_scraper_and_save())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/app/etl/extract/youtube_extract.py b/app/etl/extract/youtube_extract.py new file mode 100644 index 0000000..bd3b418 --- /dev/null +++ b/app/etl/extract/youtube_extract.py @@ -0,0 +1,66 @@ +from googleapiclient.discovery import build +from typing import Dict, Any, List +import uuid +from datetime import datetime +from loguru import logger + +class YouTubeExtractor: + def __init__(self, api_key: str): + self.youtube = build('youtube', 'v3', developerKey=api_key) + + def extract_playlist_videos(self, playlist_id: str) -> List[Dict[str, Any]]: + try: + videos = [] + next_page_token = None + + while True: + playlist_items = self.youtube.playlistItems().list( + part='snippet,contentDetails', + playlistId=playlist_id, + maxResults=50, + pageToken=next_page_token + ).execute() + + for item in playlist_items['items']: + video = self._process_video(item) + if video: + videos.append(video) + + next_page_token = playlist_items.get('nextPageToken') + if not next_page_token: + break + + return videos + + except Exception as e: + logger.error(f"Error extracting playlist {playlist_id}: {str(e)}") + return [] + + def _process_video(self, item: Dict[str, Any]) -> Dict[str, Any]: + try: + snippet = item['snippet'] + + return { + "id": str(uuid.uuid4()), + "type": "youtube_content", + "subdomain": "ros2", + "source": { + "url": f"https://www.youtube.com/watch?v={item['contentDetails']['videoId']}", + "platform": "youtube", + "video_id": item['contentDetails']['videoId'], + "last_updated": datetime.now().isoformat() + }, + "content": { + "title": snippet['title'], + "description": snippet['description'], + "thumbnails": snippet['thumbnails'] + }, + "metadata": { + "crawl_timestamp": datetime.now().isoformat(), + "channel_title": snippet['channelTitle'], + "published_at": snippet['publishedAt'] + } + } + except Exception as e: + logger.error(f"Error processing video: {str(e)}") + return None \ No newline at end of file diff --git a/app/etl/transform/feature_extractor.py b/app/etl/transform/feature_extractor.py new file mode 100644 index 0000000..2be8040 --- /dev/null +++ b/app/etl/transform/feature_extractor.py @@ -0,0 +1,83 @@ +from typing import Dict, Any, List +from sentence_transformers import SentenceTransformer +import torch +from loguru import logger +from tqdm import tqdm + +class FeatureExtractor: + def __init__(self, model_name: str = "all-MiniLM-L6-v2"): + """Initialize the feature extractor with a sentence transformer model""" + self.model = SentenceTransformer(model_name) + self.device = 'cuda' if torch.cuda.is_available() else 'cpu' + self.model.to(self.device) + + def _prepare_text_chunks(self, document: Dict[str, Any]) -> List[Dict[str, Any]]: + """Split document into chunks suitable for embedding""" + chunks = [] + if document.get('content', {}).get('title'): + chunks.append({ + 'text': document['content']['title'], + 'type': 'title', + 'metadata': { + 'doc_id': document['id'], + 'subdomain': document['subdomain'], + 'url': document['source']['url'] + } + }) + for section in document.get('content', {}).get('sections', []): + if section.get('heading'): + chunks.append({ + 'text': section['heading'], + 'type': 'heading', + 'metadata': { + 'doc_id': document['id'], + 'subdomain': document['subdomain'], + 'url': document['source']['url'] + } + }) + + if section.get('content'): + paragraphs = section['content'].split('\n') + for para in paragraphs: + if para.strip(): + chunks.append({ + 'text': para.strip(), + 'type': 'content', + 'metadata': { + 'doc_id': document['id'], + 'subdomain': document['subdomain'], + 'url': document['source']['url'], + 'section': section['heading'] + } + }) + for code_block in document.get('content', {}).get('code_blocks', []): + if code_block.get('code'): + chunks.append({ + 'text': f"Code example ({code_block.get('language', 'unknown')}): " + f"{code_block.get('context', '')}\n{code_block['code']}", + 'type': 'code', + 'metadata': { + 'doc_id': document['id'], + 'subdomain': document['subdomain'], + 'url': document['source']['url'], + 'language': code_block.get('language'), + 'filename': code_block.get('filename') + } + }) + + return chunks + + def process_document(self, document: Dict[str, Any]) -> List[Dict[str, Any]]: + """Process a single document and return chunks with embeddings""" + try: + chunks = self._prepare_text_chunks(document) + texts = [chunk['text'] for chunk in chunks] + embeddings = self.model.encode(texts, show_progress_bar=False) + for chunk, embedding in zip(chunks, embeddings): + chunk['embedding'] = embedding.tolist() + + return chunks + + except Exception as e: + logger.error(f"Error processing document {document.get('id')}: {str(e)}") + return [] \ No newline at end of file diff --git a/app/jupyter_notebook_config.py b/app/jupyter_notebook_config.py new file mode 100644 index 0000000..a839428 --- /dev/null +++ b/app/jupyter_notebook_config.py @@ -0,0 +1,6 @@ +c = get_config() +c.NotebookApp.ip = '0.0.0.0' +c.NotebookApp.port = 8888 +c.NotebookApp.open_browser = False +c.NotebookApp.allow_root = True +c.NotebookApp.token = '' \ No newline at end of file diff --git a/app/main.py b/app/main.py index 18085ea..e70f3e5 100644 --- a/app/main.py +++ b/app/main.py @@ -1 +1,31 @@ -print("ROS2-RAG application starting...") \ No newline at end of file +from pipelines.etl_pipeline import DocumentationETLPipeline +import asyncio +from loguru import logger + +async def main(): + try: + pipeline = DocumentationETLPipeline() + await pipeline.run() + stats = pipeline.mongo_client.get_statistics() + logger.info("ETL Pipeline Statistics:") + logger.info(f"Total Documents: {stats.get('total_documents', 0)}") + logger.info("By Subdomain:") + for subdomain, count in stats.get('by_subdomain', {}).items(): + logger.info(f" {subdomain}: {count}") + + except Exception as e: + logger.error(f"Pipeline failed: {str(e)}") + return 1 + + return 0 + +if __name__ == "__main__": + try: + exit_code = asyncio.run(main()) + exit(exit_code) + except KeyboardInterrupt: + logger.warning("Pipeline interrupted by user") + exit(1) + except Exception as e: + logger.error(f"Unexpected error: {str(e)}") + exit(1) \ No newline at end of file diff --git a/app/pipelines/clearml_etl_pipeline.py b/app/pipelines/clearml_etl_pipeline.py new file mode 100644 index 0000000..f1d73c1 --- /dev/null +++ b/app/pipelines/clearml_etl_pipeline.py @@ -0,0 +1,63 @@ +from clearml import PipelineDecorator +from typing import Dict, Any, List +from loguru import logger +import yaml + +@PipelineDecorator.component(cache=True, execution_queue="default") +def extract_documentation(config_path: str) -> List[Dict[str, Any]]: + from etl.extract.doc_extract import DocumentationExtractor + import asyncio + + with open(config_path, 'r') as f: + config = yaml.safe_load(f) + + async def run_extraction(): + extractor = DocumentationExtractor() + documents = [] + + for subdomain, details in config['sources']['documentation'].items(): + docs = await extractor.extract_docs( + base_url=details['base_url'], + sections=details['sections'], + subdomain=subdomain, + version=details['version'] + ) + documents.extend(docs) + + await extractor.close() + return documents + + return asyncio.run(run_extraction()) + +@PipelineDecorator.component(cache=True, execution_queue="default") +def store_documents(documents: List[Dict[str, Any]]) -> bool: + from utils.mongodb import MongoDBClient + + mongo_client = MongoDBClient() + success_count = 0 + + for doc in documents: + if mongo_client.insert_document(doc): + success_count += 1 + + logger.info(f"Successfully stored {success_count}/{len(documents)} documents") + return True + +@PipelineDecorator.pipeline( + name='etl_pipeline', + project='ROS2_RAG', + version='0.1' +) +def etl_pipeline_logic(config_path: str = "./app/configs/sources.yaml"): + # Extract documents + documents = extract_documentation(config_path=config_path) + + # Store documents + if documents: + store_documents(documents=documents) + + return True + +if __name__ == '__main__': + PipelineDecorator.run_locally() + etl_pipeline_logic() \ No newline at end of file diff --git a/app/pipelines/clearml_feature_pipeline.py b/app/pipelines/clearml_feature_pipeline.py new file mode 100644 index 0000000..d934a9c --- /dev/null +++ b/app/pipelines/clearml_feature_pipeline.py @@ -0,0 +1,69 @@ +from clearml import PipelineDecorator +from typing import Dict, Any, List +from loguru import logger + +@PipelineDecorator.component(cache=True, execution_queue="default") +def get_unprocessed_documents() -> List[Dict[str, Any]]: + from utils.mongodb import MongoDBClient + + mongo_client = MongoDBClient() + documents = mongo_client.get_unprocessed_documents() + logger.info(f"Found {len(documents)} unprocessed documents") + return documents + +@PipelineDecorator.component(cache=True, execution_queue="default") +def process_document_batch(documents: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + from etl.transform.feature_extractor import FeatureExtractor + + extractor = FeatureExtractor() + processed_chunks = [] + + for doc in documents: + chunks = extractor.process_document(doc) + if chunks: + processed_chunks.extend(chunks) + + return processed_chunks + +@PipelineDecorator.component(cache=True, execution_queue="default") +def store_vectors(chunks: List[Dict[str, Any]], doc_ids: List[str]) -> bool: + from utils.qdrant_client import QdrantClient + from utils.mongodb import MongoDBClient + + # Store vectors in Qdrant + vector_store = QdrantClient() + vector_store.store_vectors(chunks) + + # Mark documents as processed + mongo_client = MongoDBClient() + for doc_id in doc_ids: + mongo_client.mark_document_processed(doc_id) + + return True + +@PipelineDecorator.pipeline( + name='feature_pipeline', + project='ROS2_RAG', + version='0.1' +) +def feature_pipeline_logic(batch_size: int = 5): + # Get unprocessed documents + documents = get_unprocessed_documents() + + # Process in batches + for i in range(0, len(documents), batch_size): + batch = documents[i:i + batch_size] + doc_ids = [doc['id'] for doc in batch] + + # Process batch + chunks = process_document_batch(documents=batch) + + # Store results + if chunks: + store_vectors(chunks=chunks, doc_ids=doc_ids) + + return True + +if __name__ == '__main__': + PipelineDecorator.run_locally() + feature_pipeline_logic() \ No newline at end of file diff --git a/app/pipelines/etl_pipeline.py b/app/pipelines/etl_pipeline.py new file mode 100644 index 0000000..a9b9e41 --- /dev/null +++ b/app/pipelines/etl_pipeline.py @@ -0,0 +1,81 @@ +from clearml import Task, Logger +from typing import Dict, Any, List +from loguru import logger +import asyncio + +from etl.extract.doc_extract import DocumentationExtractor +from utils.mongodb import MongoDBClient +from utils.config import Config + +class DocumentationETLPipeline: + def __init__(self): + self.task = Task.init(project_name="ROS2_RAG", + task_name="documentation_etl") + self.config = Config() + self.extractor = DocumentationExtractor() + self.mongo_client = MongoDBClient() + self.iteration = 0 + + async def process_subdomain(self, subdomain: str, config: Dict[str, Any]): + """Process documentation for a subdomain""" + logger.info(f"Starting extraction for {subdomain}") + + base_url = config['base_url'] + sections = config['sections'] + version = config['version'] + documents = await self.extractor.extract_docs( + base_url=base_url, + sections=sections, + subdomain=subdomain, + version=version + ) + + # Store documents + successful_saves = 0 + for doc in documents: + if doc and not self.mongo_client.check_document_exists(doc['source']['url']): + success = self.mongo_client.insert_document(doc) + if success: + successful_saves += 1 + logger.info(f"Successfully stored document: {doc['source']['url']}") + + # Log metrics + self._log_metrics(subdomain, len(documents), successful_saves) + self.iteration += 1 + + def _log_metrics(self, subdomain: str, total_docs: int, saved_docs: int): + """Log metrics to ClearML""" + try: + Logger.current_logger().report_scalar( + "Extraction Stats", + f"{subdomain}_total_documents", + value=total_docs, + iteration=self.iteration + ) + Logger.current_logger().report_scalar( + "Extraction Stats", + f"{subdomain}_saved_documents", + value=saved_docs, + iteration=self.iteration + ) + except Exception as e: + logger.error(f"Error logging metrics: {str(e)}") + + async def run(self): + """Run the ETL pipeline""" + try: + docs_sources = self.config.documentation_sources + + for subdomain, config in docs_sources.items(): + await self.process_subdomain(subdomain, config) + + # Log final statistics + stats = self.mongo_client.get_statistics() + logger.info(f"ETL Pipeline completed. Total documents: {stats['total_documents']}") + + except Exception as e: + logger.error(f"Error in ETL pipeline: {str(e)}") + raise + finally: + # Clean up + await self.extractor.close() \ No newline at end of file diff --git a/app/pipelines/feature_pipeline.py b/app/pipelines/feature_pipeline.py new file mode 100644 index 0000000..545e5d9 --- /dev/null +++ b/app/pipelines/feature_pipeline.py @@ -0,0 +1,64 @@ +from typing import List, Dict, Any +from loguru import logger +from tqdm import tqdm +from clearml import Task + +from etl.transform.feature_extractor import FeatureExtractor +from utils.mongodb import MongoDBClient +from utils.qdrant_client import QdrantClient + +class FeaturePipeline: + def __init__(self): + self.task = Task.init(project_name="ROS2_RAG", + task_name="feature_pipeline") + self.extractor = FeatureExtractor() + self.mongo_client = MongoDBClient() + self.vector_store = QdrantClient() + + def process_documents(self, batch_size: int = 10): + """Process documents and store their embeddings""" + try: + # Get all unprocessed documents + documents = self.mongo_client.get_unprocessed_documents() + logger.info(f"Found {len(documents)} documents to process") + + processed_count = 0 + for i in tqdm(range(0, len(documents), batch_size)): + batch = documents[i:i + batch_size] + + for doc in batch: + # Generate embeddings for document chunks + chunks = self.extractor.process_document(doc) + + if chunks: + # Store vectors in Qdrant + self.vector_store.store_vectors(chunks) + + # Update document status in MongoDB + self.mongo_client.mark_document_processed(doc['id']) + + processed_count += 1 + + logger.info(f"Successfully processed {processed_count} documents") + + except Exception as e: + logger.error(f"Error in feature pipeline: {str(e)}") + raise + + def _log_metrics(self, processed: int, total: int): + """Log metrics to ClearML""" + try: + self.task.get_logger().report_scalar( + "Processing Stats", + "processed_documents", + value=processed, + iteration=0 + ) + self.task.get_logger().report_scalar( + "Processing Stats", + "total_documents", + value=total, + iteration=0 + ) + except Exception as e: + logger.error(f"Error logging metrics: {str(e)}") \ No newline at end of file diff --git a/app/pipelines/media_etl_pipeline.py b/app/pipelines/media_etl_pipeline.py new file mode 100644 index 0000000..87543e5 --- /dev/null +++ b/app/pipelines/media_etl_pipeline.py @@ -0,0 +1,91 @@ +from clearml import Task +from typing import Dict, Any, List +import yaml +from loguru import logger +from youtube_transcript_api import YouTubeTranscriptApi +from app.etl.extract.github_extract import GitHubExtractor +from app.etl.extract.youtube_extract import YouTubeExtractor +from app.utils.mongodb import MongoDBClient +from app.utils.config import Config + +class MediaETLPipeline: + def __init__(self): + self.task = Task.init(project_name="ROS2_RAG", + task_name="media_etl") + self.config = Config() + self.mongo_client = MongoDBClient() + + with open('app/configs/api_keys.yaml', 'r') as f: + self.api_keys = yaml.safe_load(f) + + self.github_extractor = GitHubExtractor( + access_token=self.api_keys['github']['access_token'] + ) + self.youtube_extractor = YouTubeExtractor( + api_key=self.api_keys['youtube']['api_key'] + ) + + def process_github_repos(self): + """Process GitHub repositories""" + repos = self.config.config['sources']['github_repos'] + + for domain, repo_list in repos.items(): + for repo in repo_list: + logger.info(f"Processing repo: {repo['name']}") + + for branch in repo['branches']: + try: + documents = self.github_extractor.extract_repo_content( + repo_name=repo['name'], + branch=branch + ) + for doc in documents: + if not self.mongo_client.check_document_exists(doc['source']['url']): + self.mongo_client.insert_document(doc) + logger.info(f"Stored document: {doc['source']['url']}") + + except Exception as e: + logger.error(f"Error processing repo {repo['name']}: {str(e)}") + + def process_youtube_content(self): + """Process YouTube playlists and extract transcripts""" + playlists = self.config.config['sources']['youtube_playlists'] + + for domain, channel_list in playlists.items(): + for channel in channel_list: + for playlist_id in channel['playlists']: + try: + videos = self.youtube_extractor.extract_playlist_videos(playlist_id) + + for video in videos: + if not self.mongo_client.check_document_exists(video['source']['url']): + try: + transcript = YouTubeTranscriptApi.get_transcript( + video['source']['video_id'] + ) + video['content']['transcript'] = transcript + except Exception as e: + logger.warning(f"Could not get transcript: {str(e)}") + video['content']['transcript'] = None + + self.mongo_client.insert_document(video) + logger.info(f"Stored video: {video['source']['url']}") + + except Exception as e: + logger.error(f"Error processing playlist {playlist_id}: {str(e)}") + + def run(self): + """Run the media ETL pipeline""" + try: + self.process_github_repos() + self.process_youtube_content() + stats = self.mongo_client.get_statistics() + logger.info(f"ETL Pipeline completed. Stats: {stats}") + + except Exception as e: + logger.error(f"Error in ETL pipeline: {str(e)}") + raise + +if __name__ == "__main__": + pipeline = MediaETLPipeline() + pipeline.run() \ No newline at end of file diff --git a/app/run_feature_pipeline.py b/app/run_feature_pipeline.py new file mode 100644 index 0000000..df050f1 --- /dev/null +++ b/app/run_feature_pipeline.py @@ -0,0 +1,16 @@ +import asyncio +from loguru import logger +from pipelines.feature_pipeline import FeaturePipeline + +def main(): + try: + pipeline = FeaturePipeline() + pipeline.process_documents(batch_size=5) + logger.info("Feature pipeline completed successfully") + + except Exception as e: + logger.error(f"Error running feature pipeline: {str(e)}") + raise + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/app/utils/config.py b/app/utils/config.py new file mode 100644 index 0000000..1660f0d --- /dev/null +++ b/app/utils/config.py @@ -0,0 +1,17 @@ +import os +from pathlib import Path +from typing import Dict, Any +import yaml + +class Config: + def __init__(self, config_path: str = "./app/configs/sources.yaml"): + self.config_path = Path(config_path) + self._load_config() + + def _load_config(self) -> None: + with open(self.config_path, 'r') as f: + self.config = yaml.safe_load(f) + + @property + def documentation_sources(self) -> Dict[str, Any]: + return self.config.get('sources', {}).get('documentation', {}) \ No newline at end of file diff --git a/app/utils/mongodb.py b/app/utils/mongodb.py new file mode 100644 index 0000000..2b1f98e --- /dev/null +++ b/app/utils/mongodb.py @@ -0,0 +1,90 @@ +# utils/mongodb.py +from typing import Dict, Any, List +import pymongo +from loguru import logger +from datetime import datetime + +class MongoDBClient: + def __init__(self, connection_string: str = "mongodb://localhost:27017/"): + self.client = pymongo.MongoClient(connection_string) + self.db = self.client['ros2_rag'] + self.docs_collection = self.db['documentation'] + self._setup_indexes() + + def _setup_indexes(self): + """Setup necessary indexes""" + try: + # Create indexes for common queries + self.docs_collection.create_index([("source.url", 1)], unique=True) + self.docs_collection.create_index([("subdomain", 1)]) + self.docs_collection.create_index([("type", 1)]) + # Text index for searching + self.docs_collection.create_index([ + ("content.title", "text"), + ("content.body", "text") + ]) + except Exception as e: + logger.error(f"Error setting up indexes: {e}") + + def insert_document(self, document: Dict[str, Any]) -> bool: + """Insert a document with retry logic""" + max_retries = 3 + for attempt in range(max_retries): + try: + self.docs_collection.insert_one(document) + return True + except pymongo.errors.DuplicateKeyError: + logger.warning(f"Document already exists: {document['source']['url']}") + return False + except Exception as e: + if attempt == max_retries - 1: + logger.error(f"Failed to insert document after {max_retries} attempts: {e}") + return False + logger.warning(f"Retry {attempt + 1} after error: {e}") + continue + + def check_document_exists(self, url: str) -> bool: + """Check if document exists by URL""" + return self.docs_collection.find_one({"source.url": url}) is not None + + def get_statistics(self) -> Dict[str, Any]: + """Get collection statistics""" + try: + return { + "total_documents": self.docs_collection.count_documents({}), + "by_subdomain": self._get_subdomain_stats(), + "by_type": self._get_type_stats(), + "last_update": datetime.utcnow().isoformat() + } + except Exception as e: + logger.error(f"Error getting statistics: {e}") + return {} + + def _get_subdomain_stats(self) -> Dict[str, int]: + """Get document count by subdomain""" + pipeline = [ + {"$group": {"_id": "$subdomain", "count": {"$sum": 1}}} + ] + return {doc["_id"]: doc["count"] + for doc in self.docs_collection.aggregate(pipeline)} + + def _get_type_stats(self) -> Dict[str, int]: + """Get document count by type""" + pipeline = [ + {"$group": {"_id": "$type", "count": {"$sum": 1}}} + ] + return {doc["_id"]: doc["count"] + for doc in self.docs_collection.aggregate(pipeline)} + + def get_unprocessed_documents(self) -> List[Dict[str, Any]]: + """Get documents that haven't been processed for embeddings""" + return list(self.docs_collection.find( + {"processed_for_embeddings": {"$ne": True}} + )) + + def mark_document_processed(self, doc_id: str): + """Mark a document as processed for embeddings""" + self.docs_collection.update_one( + {"id": doc_id}, + {"$set": {"processed_for_embeddings": True}} + ) \ No newline at end of file diff --git a/app/utils/qdrant_client.py b/app/utils/qdrant_client.py new file mode 100644 index 0000000..d82562e --- /dev/null +++ b/app/utils/qdrant_client.py @@ -0,0 +1,44 @@ +from qdrant_client import QdrantClient as Qdrant +from qdrant_client.models import Distance, VectorParams, PointStruct +from typing import List, Dict, Any +from loguru import logger + +class QdrantClient: + def __init__(self, host: str = "localhost", port: int = 6333): + self.client = Qdrant(host=host, port=port) + self._ensure_collection() + + def _ensure_collection(self): + """Ensure the required collection exists""" + try: + self.client.recreate_collection( + collection_name="ros2_docs", + vectors_config=VectorParams(size=384, distance=Distance.COSINE) + ) + except Exception as e: + logger.error(f"Error creating collection: {str(e)}") + + def store_vectors(self, chunks: List[Dict[str, Any]]): + """Store vectors in Qdrant""" + try: + points = [] + for i, chunk in enumerate(chunks): + points.append( + PointStruct( + id=i, + vector=chunk['embedding'], + payload={ + 'text': chunk['text'], + 'type': chunk['type'], + **chunk['metadata'] + } + ) + ) + + self.client.upsert( + collection_name="ros2_docs", + points=points + ) + + except Exception as e: + logger.error(f"Error storing vectors: {str(e)}") \ No newline at end of file diff --git a/app/verify_pipeline.py b/app/verify_pipeline.py new file mode 100644 index 0000000..23945db --- /dev/null +++ b/app/verify_pipeline.py @@ -0,0 +1,14 @@ +from utils.mongodb import MongoDBClient +from utils.qdrant_client import QdrantClient +from loguru import logger + +def verify_pipeline(): + mongo_client = MongoDBClient() + stats = mongo_client.get_statistics() + logger.info(f"MongoDB Statistics: {stats}") + qdrant_client = QdrantClient() + collection_info = qdrant_client.client.get_collection('ros2_docs') + logger.info(f"Qdrant Collection Info: {collection_info}") + +if __name__ == "__main__": + verify_pipeline() \ No newline at end of file diff --git a/assets/Example-prompt-1.png b/assets/Example-prompt-1.png new file mode 100644 index 0000000..535b855 Binary files /dev/null and b/assets/Example-prompt-1.png differ diff --git a/assets/Example-prompt-2.png b/assets/Example-prompt-2.png new file mode 100644 index 0000000..563e070 Binary files /dev/null and b/assets/Example-prompt-2.png differ diff --git a/assets/Model-card.png b/assets/Model-card.png new file mode 100644 index 0000000..4dbc6b5 Binary files /dev/null and b/assets/Model-card.png differ diff --git a/assets/architecture.png b/assets/architecture.png new file mode 100644 index 0000000..eb69669 Binary files /dev/null and b/assets/architecture.png differ diff --git a/assets/docker-ps.png b/assets/docker-ps.png new file mode 100644 index 0000000..c67cf70 Binary files /dev/null and b/assets/docker-ps.png differ diff --git a/assets/dropdown.png b/assets/dropdown.png new file mode 100644 index 0000000..0b40a1e Binary files /dev/null and b/assets/dropdown.png differ diff --git a/assets/etl-ingest.png b/assets/etl-ingest.png new file mode 100644 index 0000000..091572a Binary files /dev/null and b/assets/etl-ingest.png differ diff --git a/check_mongodb.py b/check_mongodb.py new file mode 100644 index 0000000..062435d --- /dev/null +++ b/check_mongodb.py @@ -0,0 +1,28 @@ +from pymongo import MongoClient +from pprint import pprint + +client = MongoClient("mongodb://localhost:27017/") +db = client['ros2_rag'] +collection = db['documentation'] + +doc = collection.find_one({ + "source.url": "https://github.com/ros2/ros2/" +}) + +if doc: + print("\nDocument found!") + print("\nDocument structure:") + print("------------------") + print(f"ID: {doc['id']}") + print(f"Type: {doc['type']}") + print(f"Subdomain: {doc['subdomain']}") + print("\nSource info:") + print(f"URL: {doc['source']['url']}") + print(f"Repository: {doc['source']['repo']}") + print(f"Branch: {doc['source']['branch']}") + + print("\nContent preview (first 200 chars):") + print("------------------") + print(doc['content']['body'][:900] + "...") +else: + print("Document not found!") \ No newline at end of file diff --git a/exported_docs/gazebo/Actors#.txt b/exported_docs/gazebo/Actors#.txt new file mode 100644 index 0000000..a6e020c --- /dev/null +++ b/exported_docs/gazebo/Actors#.txt @@ -0,0 +1,183 @@ +Title: Actors# +URL: https://gazebosim.org/docs/latest/actors +Section: actors +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: actor_walking +``` + + + +https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae + + +1.0 + + + + +https://fuel.gazebosim.org/1.0/Mingfei/models/actor/tip/files/meshes/walk.dae + + +true + + + +``` + +Language: unknown +File: talk_b.dae +``` + +``` diff --git a/exported_docs/gazebo/Binary Installation on MacOS Mojave (10.14)#.txt b/exported_docs/gazebo/Binary Installation on MacOS Mojave (10.14)#.txt new file mode 100644 index 0000000..7e37494 --- /dev/null +++ b/exported_docs/gazebo/Binary Installation on MacOS Mojave (10.14)#.txt @@ -0,0 +1,40 @@ +Title: Binary Installation on MacOS Mojave (10.14)# +URL: https://gazebosim.org/docs/citadel/install_osx +Section: getstarted +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +``` +/bin/bash +-c +" +$( +curl +-fsSL +https://raw.githubusercontent.com/Homebrew/install/master/install.sh +) +" +``` + +Language: unknown +``` +brew +tap +osrf/simulation +brew +install +ignition-citadel + +``` + +Language: unknown +File: igngazebo +``` +brew +uninstall +ignition-citadel + +``` diff --git a/exported_docs/gazebo/Binary Installation on Ubuntu#.txt b/exported_docs/gazebo/Binary Installation on Ubuntu#.txt new file mode 100644 index 0000000..a24af6f --- /dev/null +++ b/exported_docs/gazebo/Binary Installation on Ubuntu#.txt @@ -0,0 +1,73 @@ +Title: Binary Installation on Ubuntu# +URL: https://gazebosim.org/docs/harmonic/install_ubuntu +Section: getstarted +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: gz-harmonic +``` +sudo +apt-get +update +sudo +apt-get +install +curl +lsb-release +gnupg + +``` + +Language: unknown +File: gz-harmonic +``` +sudo +curl +https://packages.osrfoundation.org/gazebo.gpg +--output +/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg + +echo +"deb [arch= +$( +dpkg +--print-architecture +) + signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable +$( +lsb_release +-cs +) + main" +| +sudo +tee +/etc/apt/sources.list.d/gazebo-stable.list +> +/dev/null +sudo +apt-get +update +sudo +apt-get +install +gz-harmonic + +``` + +Language: unknown +File: gzsim +``` +sudo +apt +remove +gz-harmonic +&& +sudo +apt +autoremove + +``` diff --git a/exported_docs/gazebo/Binary Installation on macOS#.txt b/exported_docs/gazebo/Binary Installation on macOS#.txt new file mode 100644 index 0000000..ac6eebf --- /dev/null +++ b/exported_docs/gazebo/Binary Installation on macOS#.txt @@ -0,0 +1,40 @@ +Title: Binary Installation on MacOS# +URL: https://gazebosim.org/docs/fortress/install_osx +Section: getstarted +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +``` +/bin/bash +-c +" +$( +curl +-fsSL +https://raw.githubusercontent.com/Homebrew/install/master/install.sh +) +" +``` + +Language: unknown +``` +brew +tap +osrf/simulation +brew +install +ignition-fortress + +``` + +Language: unknown +File: igngazebo-s +``` +brew +uninstall +ignition-fortress + +``` diff --git a/exported_docs/gazebo/Building your own robot#.txt b/exported_docs/gazebo/Building your own robot#.txt new file mode 100644 index 0000000..be57236 --- /dev/null +++ b/exported_docs/gazebo/Building your own robot#.txt @@ -0,0 +1,721 @@ +Title: Building your own robot# +URL: https://gazebosim.org/docs/latest/building_robot +Section: building_robot +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: building_robot.sdf +``` + + + + + +0.001 + + +1.0 + + + + + + + + + + +true + + +0 +0 +10 +0 +0 +0 + + +0.8 +0.8 +0.8 +1 + + +0.2 +0.2 +0.2 +1 + + + +1000 + + +0.9 + + +0.01 + + +0.001 + + + +-0.5 +0.1 +-0.9 + + + + +true + + + + + + +0 +0 +1 + + + + + + + + +0 +0 +1 + + +100 +100 + + + + + +0.8 +0.8 +0.8 +1 + + +0.8 +0.8 +0.8 +1 + + +0.8 +0.8 +0.8 +1 + + + + + + + +``` + +Language: unknown +File: +``` + + +0 +0 +0 +0 +0 +0 + +``` + +Language: unknown +File: joints +``` + + +0.5 +0 +0.4 +0 +0 +0 + +``` + +Language: unknown +File: model +``` + + + +1.14395 + + + +0.095329 + + +0 + + +0 + + +0.381317 + + +0 + + +0.476646 + + + +``` + +Language: unknown +File: +``` + + + + +2.0 +1.0 +0.5 + + + + + + +0.0 +0.0 +1.0 +1 + + +0.0 +0.0 +1.0 +1 + + +0.0 +0.0 +1.0 +1 + + + +``` + +Language: unknown +File: +``` + + + + +2.0 +1.0 +0.5 + + + + + + +``` + +Language: unknown +File: +``` + + +-0.5 +0.6 +0 +-1.5707 +0 +0 + + + +1 + + + +0.043333 + + +0 + + +0 + + +0.043333 + + +0 + + +0.08 + + + +``` + +Language: unknown +File: inertia +``` + + + + +0.4 + + +0.2 + + + + + +1.0 +0.0 +0.0 +1 + + +1.0 +0.0 +0.0 +1 + + +1.0 +0.0 +0.0 +1 + + + + + + + +0.4 + + +0.2 + + + + + +``` + +Language: unknown +File: +``` + + + +-0.5 +-0.6 +0 +-1.5707 +0 +0 + + + + +1 + + + +0.043333 + + +0 + + +0 + + +0.043333 + + +0 + + +0.08 + + + + + + + +0.4 + + +0.2 + + + + + +1.0 +0.0 +0.0 +1 + + +1.0 +0.0 +0.0 +1 + + +1.0 +0.0 +0.0 +1 + + + + + + + +0.4 + + +0.2 + + + + + +``` + +Language: unknown +File: attached_to +``` + + +0.8 +0 +-0.2 +0 +0 +0 + + +``` + +Language: unknown +File: chassis +``` + + + + + +1 + + + +0.016 + + +0 + + +0 + + +0.016 + + +0 + + +0.016 + + + + + + + +0.2 + + + + + +0.0 +1 +0.0 +1 + + +0.0 +1 +0.0 +1 + + +0.0 +1 +0.0 +1 + + + + + + + +0.2 + + + + + +``` + +Language: unknown +File: +``` + + +``` + +Language: unknown +File: left_wheel +``` + +chassis + + +left_wheel + +``` + +Language: unknown +File: left_wheel +``` + + +0 +1 +0 + + + + +-1.79769e+308 + + + +1.79769e+308 + + + + + +``` + +Language: unknown +File: chassis +``` + + + +chassis + + +right_wheel + + + +0 +1 +0 + + + +-1.79769e+308 + + + +1.79769e+308 + + + + + +``` + +Language: unknown +File: type='ball' +``` + + +chassis + + +caster + + +``` diff --git a/exported_docs/gazebo/Gazebo Cmake.txt b/exported_docs/gazebo/Gazebo Cmake.txt new file mode 100644 index 0000000..5e0adc4 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Cmake.txt @@ -0,0 +1,5 @@ +Title: Gazebo Cmake +URL: https://gazebosim.org/api/cmake/3/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Common.txt b/exported_docs/gazebo/Gazebo Common.txt new file mode 100644 index 0000000..12b1dcc --- /dev/null +++ b/exported_docs/gazebo/Gazebo Common.txt @@ -0,0 +1,5 @@ +Title: Gazebo Common +URL: https://gazebosim.org/api/common/5/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Fuel_tools.txt b/exported_docs/gazebo/Gazebo Fuel_tools.txt new file mode 100644 index 0000000..ad1fa77 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Fuel_tools.txt @@ -0,0 +1,5 @@ +Title: Gazebo Fuel_tools +URL: https://gazebosim.org/api/fuel_tools/9/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Garden#.txt b/exported_docs/gazebo/Gazebo Garden#.txt new file mode 100644 index 0000000..827474c --- /dev/null +++ b/exported_docs/gazebo/Gazebo Garden#.txt @@ -0,0 +1,5 @@ +Title: Gazebo Garden# +URL: https://gazebosim.org/docs/garden/install +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Gui.txt b/exported_docs/gazebo/Gazebo Gui.txt new file mode 100644 index 0000000..e54d431 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Gui.txt @@ -0,0 +1,5 @@ +Title: Gazebo Gui +URL: https://gazebosim.org/api/gui/8/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Harmonic#.txt b/exported_docs/gazebo/Gazebo Harmonic#.txt new file mode 100644 index 0000000..e70eb50 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Harmonic#.txt @@ -0,0 +1,5 @@ +Title: Gazebo Harmonic# +URL: https://gazebosim.org/docs/harmonic/install +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Ionic#.txt b/exported_docs/gazebo/Gazebo Ionic#.txt new file mode 100644 index 0000000..70b236d --- /dev/null +++ b/exported_docs/gazebo/Gazebo Ionic#.txt @@ -0,0 +1,5 @@ +Title: Gazebo Ionic# +URL: https://gazebosim.org/docs/ionic/install +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Launch.txt b/exported_docs/gazebo/Gazebo Launch.txt new file mode 100644 index 0000000..149bbea --- /dev/null +++ b/exported_docs/gazebo/Gazebo Launch.txt @@ -0,0 +1,5 @@ +Title: Gazebo Launch +URL: https://gazebosim.org/api/launch/7/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Math.txt b/exported_docs/gazebo/Gazebo Math.txt new file mode 100644 index 0000000..c339cfa --- /dev/null +++ b/exported_docs/gazebo/Gazebo Math.txt @@ -0,0 +1,5 @@ +Title: Gazebo Math +URL: https://gazebosim.org/api/math/7/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Msgs.txt b/exported_docs/gazebo/Gazebo Msgs.txt new file mode 100644 index 0000000..71f8e72 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Msgs.txt @@ -0,0 +1,5 @@ +Title: Gazebo Msgs +URL: https://gazebosim.org/api/msgs/10/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Physics.txt b/exported_docs/gazebo/Gazebo Physics.txt new file mode 100644 index 0000000..53da197 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Physics.txt @@ -0,0 +1,5 @@ +Title: Gazebo Physics +URL: https://gazebosim.org/api/physics/7/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Plugin.txt b/exported_docs/gazebo/Gazebo Plugin.txt new file mode 100644 index 0000000..ccb8beb --- /dev/null +++ b/exported_docs/gazebo/Gazebo Plugin.txt @@ -0,0 +1,5 @@ +Title: Gazebo Plugin +URL: https://gazebosim.org/api/plugin/2/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Rendering.txt b/exported_docs/gazebo/Gazebo Rendering.txt new file mode 100644 index 0000000..925fb9e --- /dev/null +++ b/exported_docs/gazebo/Gazebo Rendering.txt @@ -0,0 +1,5 @@ +Title: Gazebo Rendering +URL: https://gazebosim.org/api/rendering/8/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Sensors.txt b/exported_docs/gazebo/Gazebo Sensors.txt new file mode 100644 index 0000000..2f09620 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Sensors.txt @@ -0,0 +1,5 @@ +Title: Gazebo Sensors +URL: https://gazebosim.org/api/sensors/8/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Sim Architecture#.txt b/exported_docs/gazebo/Gazebo Sim Architecture#.txt new file mode 100644 index 0000000..8d9657e --- /dev/null +++ b/exported_docs/gazebo/Gazebo Sim Architecture#.txt @@ -0,0 +1,5 @@ +Title: Gazebo Sim Architecture# +URL: https://gazebosim.org/docs/latest/architecture +Section: architecture +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Sim.txt b/exported_docs/gazebo/Gazebo Sim.txt new file mode 100644 index 0000000..fd62a44 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Sim.txt @@ -0,0 +1,5 @@ +Title: Gazebo Sim +URL: https://gazebosim.org/api/sim/8/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Tools.txt b/exported_docs/gazebo/Gazebo Tools.txt new file mode 100644 index 0000000..ac65c63 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Tools.txt @@ -0,0 +1,5 @@ +Title: Gazebo Tools +URL: https://gazebosim.org/api/tools/2/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Transport.txt b/exported_docs/gazebo/Gazebo Transport.txt new file mode 100644 index 0000000..a665194 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Transport.txt @@ -0,0 +1,5 @@ +Title: Gazebo Transport +URL: https://gazebosim.org/api/transport/13/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Tutorials#.txt b/exported_docs/gazebo/Gazebo Tutorials#.txt new file mode 100644 index 0000000..3d8bd5d --- /dev/null +++ b/exported_docs/gazebo/Gazebo Tutorials#.txt @@ -0,0 +1,5 @@ +Title: Gazebo Tutorials# +URL: https://gazebosim.org/docs/latest/tutorials +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Gazebo Utils.txt b/exported_docs/gazebo/Gazebo Utils.txt new file mode 100644 index 0000000..6b51af6 --- /dev/null +++ b/exported_docs/gazebo/Gazebo Utils.txt @@ -0,0 +1,5 @@ +Title: Gazebo Utils +URL: https://gazebosim.org/api/utils/2/tutorials.html +Section: tutorials +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Getting Started with Gazebo?#.txt b/exported_docs/gazebo/Getting Started with Gazebo?#.txt new file mode 100644 index 0000000..4cd3143 --- /dev/null +++ b/exported_docs/gazebo/Getting Started with Gazebo?#.txt @@ -0,0 +1,74 @@ +Title: Getting Started with Gazebo?# +URL: https://gazebosim.org/docs/latest/getstarted +Section: getstarted +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +``` +gz +sim +shapes +. +sdf +# Fortress and Citadel use "ign gazebo" instead of "gz sim" +``` + +Language: unknown +File: -v4 +``` +gz +sim +shapes +. +sdf +- +v +4 +# Fortress and Citadel use "ign gazebo" instead of "gz sim" +``` + +Language: unknown +File: -s +``` +gz +sim +- +s +shapes +. +sdf +- +v +4 +# Fortress and Citadel use "ign gazebo" instead of "gz sim" +``` + +Language: unknown +File: <> +``` +# launch server in one terminal + +gz +sim +-v +4 +shapes.sdf +-s +# Fortress and Citadel use "ign gazebo" instead of "gz sim" +``` + +Language: unknown +File: <> +``` +# launch gui in a separate terminal + +gz +sim +-v +4 +-g +# Fortress and Citadel use "ign gazebo" instead of "gz sim" +``` diff --git a/exported_docs/gazebo/Ignition Citadel#.txt b/exported_docs/gazebo/Ignition Citadel#.txt new file mode 100644 index 0000000..44e5cdc --- /dev/null +++ b/exported_docs/gazebo/Ignition Citadel#.txt @@ -0,0 +1,5 @@ +Title: Ignition Citadel# +URL: https://gazebosim.org/docs/citadel/install +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Ignition Fortress#.txt b/exported_docs/gazebo/Ignition Fortress#.txt new file mode 100644 index 0000000..ab50291 --- /dev/null +++ b/exported_docs/gazebo/Ignition Fortress#.txt @@ -0,0 +1,5 @@ +Title: Ignition Fortress# +URL: https://gazebosim.org/docs/fortress/install +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Ignition Tutorials#.txt b/exported_docs/gazebo/Ignition Tutorials#.txt new file mode 100644 index 0000000..3143b80 --- /dev/null +++ b/exported_docs/gazebo/Ignition Tutorials#.txt @@ -0,0 +1,5 @@ +Title: Ignition Tutorials# +URL: https://gazebosim.org/docs/citadel/tutorials +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Installing Gazebo with ROS#.txt b/exported_docs/gazebo/Installing Gazebo with ROS#.txt new file mode 100644 index 0000000..5da19ed --- /dev/null +++ b/exported_docs/gazebo/Installing Gazebo with ROS#.txt @@ -0,0 +1,21 @@ +Title: Installing Gazebo with ROS# +URL: https://gazebosim.org/docs/latest/ros_installation +Section: ros_installation +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: noetic +``` +sudo +apt-get +install +ros- +${ +ROS_DISTRO +} +-ros-gz + +``` diff --git a/exported_docs/gazebo/Libraries#.txt b/exported_docs/gazebo/Libraries#.txt new file mode 100644 index 0000000..a592377 --- /dev/null +++ b/exported_docs/gazebo/Libraries#.txt @@ -0,0 +1,5 @@ +Title: Libraries# +URL: https://gazebosim.org/libs +Section: getstarted +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/Manipulating Models#.txt b/exported_docs/gazebo/Manipulating Models#.txt new file mode 100644 index 0000000..5611c7f --- /dev/null +++ b/exported_docs/gazebo/Manipulating Models#.txt @@ -0,0 +1,15 @@ +Title: Manipulating Models# +URL: https://gazebosim.org/docs/latest/manipulating_models +Section: manipulating_models +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +``` +gz +sim +shapes.sdf + +``` diff --git a/exported_docs/gazebo/Moving the robot#.txt b/exported_docs/gazebo/Moving the robot#.txt new file mode 100644 index 0000000..c7004de --- /dev/null +++ b/exported_docs/gazebo/Moving the robot#.txt @@ -0,0 +1,141 @@ +Title: Moving the robot# +URL: https://gazebosim.org/docs/latest/moving_robot +Section: moving_robot +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: vehicle_blue +``` + + +left_wheel_joint + + +right_wheel_joint + + +1.2 + + +0.4 + + +1 + + +cmd_vel + + +``` + +Language: unknown +File: gztopic-e-t/keyboard/keypress +``` +$ gz topic -e -t /keyboard/keypress +data: 68 + +data: 85 + +data: 72 + +data: 74 + +data: 81 + +data: 16777235 + +data: 16777234 + +data: 16777237 + +data: 16777236 + +``` + +Language: unknown +File: +``` + + + + +16777235 + + + +linear: +{x: +0.5}, +angular: +{z: +0.0} + + + +``` + +Language: unknown +File: Triggeredpublisher +``` + + + + +16777237 + + + +linear: +{x: +-0.5}, +angular: +{z: +0.0} + + + +``` diff --git a/exported_docs/gazebo/ROS 2 integration overview#.txt b/exported_docs/gazebo/ROS 2 integration overview#.txt new file mode 100644 index 0000000..0012208 --- /dev/null +++ b/exported_docs/gazebo/ROS 2 integration overview#.txt @@ -0,0 +1,5 @@ +Title: ROS 2 integration overview# +URL: https://gazebosim.org/docs/latest/ros2_overview +Section: ros2_overview +-------------------------------------------------------------------------------- + diff --git a/exported_docs/gazebo/SDF worlds#.txt b/exported_docs/gazebo/SDF worlds#.txt new file mode 100644 index 0000000..f035a24 --- /dev/null +++ b/exported_docs/gazebo/SDF worlds#.txt @@ -0,0 +1,605 @@ +Title: SDF worlds# +URL: https://gazebosim.org/docs/latest/sdf_worlds +Section: sdf_worlds +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +``` + + + +... + +... + + + +``` + +Language: unknown +File: +``` + + +0.001 + + +1.0 + + +``` + +Language: unknown +File: +``` + + +``` + +Language: unknown +File: Physics +``` + + +``` + +Language: unknown +File: UserCommands +``` + + +``` + +Language: unknown +File: GUI +``` + +... + +... + + +``` + +Language: unknown +File: GUI +``` + + + + +3D +View + + +false + + +docked + + + +ogre2 + + +scene + + +0.4 +0.4 +0.4 + + +0.8 +0.8 +0.8 + + +-6 +0 +6 +0 +0.5 +0 + + + +0.25 + + +25000 + + + + + + +false + + +5 + + +5 + + +floating + + +false + + + +``` + +Language: unknown +File: RollPitchYaw +``` + + + + +World +control + + +false + + +false + + +72 + + +121 + + +1 + + +floating + + + + + + + +true + + +true + + +true + + +/world/world_demo/control + + +/world/world_demo/stats + + +``` + +Language: unknown +File: true +``` + + + + +World +stats + + +false + + +false + + +110 + + +290 + + +1 + + +floating + + + + + + + +true + + +true + + +true + + +true + + +/world/world_demo/stats + + +``` + +Language: unknown +File: gztopic-e-t/world/world_demo/stats +``` + + + +``` + +Language: unknown +File: +``` + + +true + + +0 +0 +10 +0 +0 +0 + + +0.8 +0.8 +0.8 +1 + + +0.2 +0.2 +0.2 +1 + + + +1000 + + +0.9 + + +0.01 + + +0.001 + + + +-0.5 +0.1 +-0.9 + + +``` + +Language: unknown +File: +``` + + +https://fuel.gazebosim.org/1.0/OpenRobotics/models/Coke + + + +``` + +Language: unknown +File: +``` + + +model://Coke + + + +``` + +Language: unknown +File: GZ_SIM_RESOURCE_PATH +``` +world_tutorial
+├── Coke
+└── world_demo.sdf + +``` + +Language: unknown +File: +``` +< +include +> +< +name +> +Coke0 + +< +pose +> +0 +0 +0 +0 +0 +0 + +< +uri +> +https +: +// +fuel +. +gazebosim +. +org +/ +1.0 +/ +OpenRobotics +/ +models +/ +Coke + + +< +include +> +< +name +> +Coke1 + +< +pose +> +0 +0.1 +0 +0 +0 +0 + +< +uri +> +https +: +// +fuel +. +gazebosim +. +org +/ +1.0 +/ +OpenRobotics +/ +models +/ +Coke + + +``` diff --git a/exported_docs/gazebo/Sensors#.txt b/exported_docs/gazebo/Sensors#.txt new file mode 100644 index 0000000..1964959 --- /dev/null +++ b/exported_docs/gazebo/Sensors#.txt @@ -0,0 +1,733 @@ +Title: Sensors# +URL: https://gazebosim.org/docs/latest/sensors +Section: sensors +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: plugin +``` + + + + + + + +``` + +Language: unknown +File: +``` + + +``` + +Language: unknown +File: IMU +``` + + +1 + + +1 + + +true + + +imu + + +``` + +Language: unknown +File: contact +``` + + +true + + +5 +0 +0 +0 +0 +0 + + + + + + + +0.5 +10.0 +2.0 + + + + + + +0.0 +0.0 +1.0 +1 + + +0.0 +0.0 +1.0 +1 + + +0.0 +0.0 +1.0 +1 + + + + + + + +0.5 +10.0 +2.0 + + + + + + +``` + +Language: unknown +File: Contact +``` + + +``` + +Language: unknown +File: wall +``` + + + +collision + + + +``` + +Language: unknown +File: wall +``` + + +vehicle_blue + + +wall + + + +true + + +``` + +Language: unknown +File: TriggeredPublisher +``` + + + +data: +true + + + +linear: +{x: +0.0}, +angular: +{z: +0.0} + + + +``` + +Language: unknown +File: chassis +``` + + +0.8 +0 +0.5 +0 +0 +0 + + +``` + +Language: unknown +File: lidar +``` + + +ogre2 + + +``` + +Language: unknown +File: lidar +``` + +" + + +0 +0 +0 +0 +0 +0 + + +lidar + + +10 + + + + + +640 + + +1 + + +-1.396263 + + +1.396263 + + + + +1 + + +0.01 + + +0 + + +0 + + + + + +0.08 + + +10.0 + + +0.01 + + + + +1 + + +true + + +``` + +Language: unknown +File: gztopic-e-t/lidar +``` +message +LaserScan +{ +Header +header += +1 +; +string +frame += +2 +; +Pose +world_pose += +3 +; +double +angle_min += +4 +; +double +angle_max += +5 +; +double +angle_step += +6 +; +double +range_min += +7 +; +double +range_max += +8 +; +uint32 +count += +9 +; +double +vertical_angle_min += +10 +; +double +vertical_angle_max += +11 +; +double +vertical_angle_step += +12 +; +uint32 +vertical_count += +13 +; +repeated +double +ranges += +14 +; +repeated +double +intensities += +15 +; +} +``` + +Language: unknown +File: subscriber +``` +std +:: +string +topic_pub += +"/cmd_vel" +; +gz +:: +transport +:: +Node +node +; +auto +pub += +node +. +Advertise +< +gz +:: +msgs +:: +Twist +> +( +topic_pub +); +``` + +Language: unknown +File: cmd_vel +``` +void +cb +( +const +gz +:: +msgs +:: +LaserScan +& +_msg +) +{ +gz +:: +msgs +:: +Twist +data +; +bool +allMore += +true +; +for +( +int +i += +0 +; +i +< +_msg +. +ranges_size +(); +i +++ +) +{ +if +( +_msg +. +ranges +( +i +) +< +1.0 +) +{ +allMore += +false +; +break +; +} +} +if +( +allMore +) +//if all bigger than one +{ +data +. +mutable_linear +() +-> +set_x +( +0.5 +); +data +. +mutable_angular +() +-> +set_z +( +0.0 +); +} +else +{ +data +. +mutable_linear +() +-> +set_x +( +0.0 +); +data +. +mutable_angular +() +-> +set_z +( +0.5 +); +} +pub +. +Publish +( +data +); +} +``` + +Language: unknown +File: 1.0 +``` +int +main +( +int +argc +, +char +** +argv +) +{ +std +:: +string +topic_sub += +"/lidar" +; +// Subscribe to a topic by registering a callback. +if +( +! +node +. +Subscribe +( +topic_sub +, +cb +)) +{ +std +:: +cerr +<< +"Error subscribing to topic [" +<< +topic_sub +<< +"]" +<< +std +:: +endl +; +return +-1 +; +} +// Zzzzzz. +gz +:: +transport +:: +waitForShutdown +(); +return +0 +; +} +``` + +Language: unknown +File: build/ +``` +mkdir +build + +cd +build + +``` + +Language: unknown +File: build/ +``` +cmake +.. +make +lidar_node + +``` + +Language: unknown +File: build/ +``` +./build/lidar_node + +``` + +Language: unknown +File: build/ +``` +gz +sim +sensor_tutorial.sdf + +``` + +Language: unknown +File: lidar_node +``` + + + + +gz +sim +sensor_tutorial.sdf + + + + +./build/lidar_node + + + +``` + +Language: unknown +File: sensor_launch.gzlaunch +``` +gz +launch +sensor_launch.gzlaunch + +``` diff --git a/exported_docs/gazebo/Understanding the GUI#.txt b/exported_docs/gazebo/Understanding the GUI#.txt new file mode 100644 index 0000000..61425a5 --- /dev/null +++ b/exported_docs/gazebo/Understanding the GUI#.txt @@ -0,0 +1,44 @@ +Title: Understanding the GUI# +URL: https://gazebosim.org/docs/latest/gui +Section: gui +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +``` +gz +sim +shapes.sdf + +``` + +Language: unknown +File: --versions +``` +9 +.0.0 + +8 +.0.0 + +7 +.0.0 + +6 +.0.0 + +``` + +Language: unknown +File: --force-version +``` +gz +sim +--force-version +9 +.0.0 +shapes.sdf + +``` diff --git "a/exported_docs/moveit2/API Documentation\357\203\201.txt" "b/exported_docs/moveit2/API Documentation\357\203\201.txt" new file mode 100644 index 0000000..31ae037 --- /dev/null +++ "b/exported_docs/moveit2/API Documentation\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: API Documentation +URL: https://moveit.picknik.ai/main/doc/api/api.html +Section: index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Concepts\357\203\201.txt" "b/exported_docs/moveit2/Concepts\357\203\201.txt" new file mode 100644 index 0000000..c8fbb82 --- /dev/null +++ "b/exported_docs/moveit2/Concepts\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Concepts +URL: https://moveit.picknik.ai/main/doc/concepts/concepts.html +Section: doc/concepts/concepts.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Contributing\357\203\201.txt" "b/exported_docs/moveit2/Contributing\357\203\201.txt" new file mode 100644 index 0000000..13422d4 --- /dev/null +++ "b/exported_docs/moveit2/Contributing\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Contributing +URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_contribute.html +Section: index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Examples\357\203\201.txt" "b/exported_docs/moveit2/Examples\357\203\201.txt" new file mode 100644 index 0000000..68a981d --- /dev/null +++ "b/exported_docs/moveit2/Examples\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Examples +URL: https://moveit.picknik.ai/main/doc/examples/examples.html +Section: doc/examples/examples.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Getting Started\357\203\201.txt" "b/exported_docs/moveit2/Getting Started\357\203\201.txt" new file mode 100644 index 0000000..1877f51 --- /dev/null +++ "b/exported_docs/moveit2/Getting Started\357\203\201.txt" @@ -0,0 +1,259 @@ +Title: Getting Started +URL: https://moveit.picknik.ai/main/doc/tutorials/getting_started/getting_started.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Install ROS 2 and colcon +MoveIt 2 currently supports multiple versions of ROS. +Install whichever version you prefer. +We primarily support ROS installed on Ubuntu 22.04 or 24.04 but other methods and platforms may work with small changes to the instructions listed below. +If you are just getting started, we recommend you use the latest stable version of ROS (Jazzy) on Ubuntu 24.04 for the most seamless experience. +It is easy to miss steps when going through the ROS 2 installation tutorial. +If you run into errors in the next few steps, a good place to start is to go back and make sure you have installed ROS 2 correctly. +One that users commonly forget is to source the ROS 2 install itself. +Note to source the version of ROS you installed. +Installrosdepto install system dependencies : +Once you have ROS 2 installed, make sure you have the most up to date packages: +InstallColconthe ROS 2 build system withmixin: +Installvcstool: + +## Create A Colcon Workspace and Download Tutorials +For tutorials you will need to have acolconworkspace setup. + +## Download Source Code of MoveIt and the Tutorials +Move into your Colcon workspace and pull the MoveIt tutorials source, wherecan be e.g.humblefor ROS Humble, ormainfor the latest version of the tutorials : +Next we will download the source code for the rest of MoveIt: +The import command may ask for your GitHub credentials. +You can just press Enter until it moves on (ignore the “Authentication failed” error). + +## Build your Colcon Workspace +First remove all previously installed moveit binaries: +The following will install from Debian any package dependencies not already in your workspace. +This is the step that will install MoveIt and all of its dependencies: +The next command will configure your Colcon workspace: +This build command will likely take a long time (20+ minutes) depending on your computer speed and amount of RAM available (we recommend 32 GB). +If everything goes well, you should see the message “Summary: X packages finished” where X might be 50. If you have problems, try re-checking yourROS Installation. + +## Setup Your Colcon Workspace +Source the Colcon workspace: +Optional: add the previous command to your.bashrc: + +## Next Step +Nice job! +Next, we willVisualize a robot with the interactive motion planning plugin for RViz + +Code Examples: + +Language: unknown +``` +source +/ +opt +/ +ros +/ +jazzy +/ +setup +. +bash +``` + +Language: unknown +File: .bashrc +``` +sudo +apt +install +python3 +- +rosdep +``` + +Language: unknown +File: .bashrc +``` +sudo +rosdep +init +rosdep +update +sudo +apt +update +sudo +apt +dist +- +upgrade +``` + +Language: unknown +File: .bashrc +``` +sudo +apt +install +python3 +- +colcon +- +common +- +extensions +sudo +apt +install +python3 +- +colcon +- +mixin +colcon +mixin +add +default +https +: +// +raw +. +githubusercontent +. +com +/ +colcon +/ +colcon +- +mixin +- +repository +/ +master +/ +index +. +yaml +colcon +mixin +update +default +``` + +Language: unknown +File: .bashrc +``` +sudo +apt +install +python3 +- +vcstool +``` + +Language: unknown +File: .bashrc +``` +mkdir +- +p +~/ +ws_moveit +/ +src +``` + +Language: unknown +File: main +``` +cd +~/ +ws_moveit +/ +src +git +clone +- +b +< +branch +> +https +: +// +github +. +com +/ +moveit +/ +moveit2_tutorials +``` + +Language: unknown +File: main +``` +vcs +import +-- +recursive +< +moveit2_tutorials +/ +moveit2_tutorials +. +repos +``` + +Language: unknown +File: main +``` +sudo apt remove ros-$ROS_DISTRO-moveit* + +``` + +Language: unknown +File: main +``` +sudo apt update && rosdep install -r --from-paths . --ignore-src --rosdistro $ROS_DISTRO -y + +``` + +Language: unknown +File: main +``` +cd +~/ +ws_moveit +colcon +build +-- +mixin +release +``` + +Language: unknown +File: MAKEFLAGS="-j4-l1"colconbuild--executorsequential +``` +source +~/ +ws_moveit +/ +install +/ +setup +. +bash +``` + +Language: unknown +File: .bashrc +``` +echo +'source ~/ws_moveit/install/setup.bash' +>> +~/. +bashrc +``` diff --git "a/exported_docs/moveit2/How to Contribute to This Site\357\203\201.txt" "b/exported_docs/moveit2/How to Contribute to This Site\357\203\201.txt" new file mode 100644 index 0000000..10ca3d8 --- /dev/null +++ "b/exported_docs/moveit2/How to Contribute to This Site\357\203\201.txt" @@ -0,0 +1,131 @@ +Title: How to Contribute to This Site +URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_contribute_to_site.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Learning Objectives + + +## Requirements + + +## Steps + + +## Further Reading + + +Code Examples: + +Language: unknown +File: ~/ws_moveit/src/moveit2_tutorials +``` +make +html + +# Or run the following lines if you want to automatically rebuild the website on new changes +while +inotifywait +-re +modify,move,create,delete +. +; +do +make +html + +done +``` + +Language: unknown +File: ./build/html/index.html +``` +xdg-open +./build/html/index.html + +``` + +Language: unknown +File: pip +``` +python3 +-m +venv +.venv + +source +.venv/bin/activate + +``` + +Language: unknown +File: pip +``` +pip3 +install +--upgrade +--requirement +requirements.txt + +``` + +Language: unknown +File: htmlproofer +``` +./htmlproofer.sh + +``` + +Language: unknown +File: htmlproofer +``` +python3 +-m +pip +install +--user +pre-commit + +``` + +Language: unknown +File: htmlproofer +``` +pre-commit +run +--all + +``` + +Language: unknown +File: htmlproofer +``` +ros2 +run +industrial_ci +rerun_ci +src/moveit2_tutorials +\ +DOCKER_IMAGE += +'moveit/moveit2:rolling-source' +\ +UPSTREAM_WORKSPACE += +'moveit2_tutorials.repos' +\ +TARGET_CMAKE_ARGS += +'-DCMAKE_BUILD_TYPE=Release' +\ +CCACHE_DIR += +" +$HOME +/.ccache" +\ +CLANG_TIDY += +'true' +``` diff --git "a/exported_docs/moveit2/How to Cross-Reference Content\357\203\201.txt" "b/exported_docs/moveit2/How to Cross-Reference Content\357\203\201.txt" new file mode 100644 index 0000000..191955d --- /dev/null +++ "b/exported_docs/moveit2/How to Cross-Reference Content\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: How to Cross-Reference Content +URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_cross_reference.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Learning Objectives + + +## Linking to other Documents and Sections +Sphinx provides the:doc:and:ref:roles forcross-referencing contentand it’s best to stick to them to ensure compatibility with other Sphinx extensions and multi-distro support. +For linking to other documents, you can use the:doc:role like this:Getting Started(:doc:`/doc/tutorials/getting_started/getting_started`). The:ref:role accepts ids that link to explicit targets on a page. +For convenience, we have enabled the Sphinx extensionautosectionlabelwhich creates unique and human-readable reference targets for all sections. +Sections in all documents can be linked by providing the document path and the section titlelike this(:ref:`likethis`). +Note that the:doc:role requires absolute paths to start with a/while theautosectionlabelextension builds:refpath labels without it. + +## Referencing the API Documentation +The API pages are generated using Doxygen and not Sphinx which means that:doc:and:ref:roles are not able to find any API pages. +We are usingdoxylinkand the custom:cpp_api:role for generating links to the API pages from symbols. +Here are some examples, take note that some links use titles and some not: +If you are unsure about how to link certain symbols, you can find all Doxygen references inside theMoveIt.tagfile. +The file is located insidebuild/html/api/orbuild/html//api/depending on the build type. + +## Do’s and Don’ts +Pleasedo: +Pleasedon’t: + +## Further Reading + diff --git "a/exported_docs/moveit2/How to Write a MoveIt How-To Guide\357\203\201.txt" "b/exported_docs/moveit2/How to Write a MoveIt How-To Guide\357\203\201.txt" new file mode 100644 index 0000000..463de22 --- /dev/null +++ "b/exported_docs/moveit2/How to Write a MoveIt How-To Guide\357\203\201.txt" @@ -0,0 +1,120 @@ +Title: How to Write a MoveIt How-To Guide +URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_write_how_to_guides.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Learning Objectives + + +## Requirements + + +## Steps + + +## Template + + +## Further Reading + + +Code Examples: + +Language: unknown +File: .rst +``` +< +Title +> +------- +< +Brief +description +of +the +How +- +To +Guide +with +image +or +GIF +showing +the +outcome +.> +Learning +Objectives +------------------- +< +List +of +things +the +user +will +learn +.> +Requirements +---------- +< +Explanation +of +what +the +user +should +understand +. +Unlike +a +tutorial +, +these +guides +stand +alone +and +can +assume +the +user +has +much +more +background +.> +Steps +----- +< +A +list +of +steps +to +take +to +solve +the +problem +.> +Further +Reading +--------------- +< +A +list +of +links +to +related +content +on +and +off +this +website +.> +``` diff --git "a/exported_docs/moveit2/How to Write a MoveIt Tutorial\357\203\201.txt" "b/exported_docs/moveit2/How to Write a MoveIt Tutorial\357\203\201.txt" new file mode 100644 index 0000000..59cfd1d --- /dev/null +++ "b/exported_docs/moveit2/How to Write a MoveIt Tutorial\357\203\201.txt" @@ -0,0 +1,184 @@ +Title: How to Write a MoveIt Tutorial +URL: https://moveit.picknik.ai/main/doc/how_to_contribute/how_to_write_tutorials.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Learning Objectives + + +## Requirements + + +## Steps + + +## Template + + +## Further Reading + + +Code Examples: + +Language: unknown +File: .rst +``` +< +Title +> +------- +< +Brief +description +of +the +tutorial +with +image +showing +what +will +be +accomplished +.> +Background +---------- +< +Explanation +of +what +the +user +should +have +already +done +before +this +tutorial +.> +Steps +----- +1. +< +First +Step +> +--------------- +< +This +should +describe +an +action +that +the +user +should +take +such +as +creating +a +ROS +project +or +typing +up +some +code +.> +1.1 +) +< +Explanation +First +Step +> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +< +Use +sub +- +steps +like +this +to +walk +the +user +through +an +explanation +of +what +they +did +.> +1.2 +) +< +Action +First +step +> +^^^^^^^^^^^^^^^^^^^^^^^ +< +Use +a +sub +- +step +like +this +to +describe +running +the +new +code +and +what +the +results +should +be +.> +2. +< +Second +Step +> +---------------- +<...> +Conclusion +---------- +< +Here +is +where +you +explain +what +the +user +has +read +and +provide +additional +references +.> +Next +Step +--------- +< +Link +to +the +next +tutorial +here +.> +``` diff --git "a/exported_docs/moveit2/How-To Guides\357\203\201.txt" "b/exported_docs/moveit2/How-To Guides\357\203\201.txt" new file mode 100644 index 0000000..0e66c74 --- /dev/null +++ "b/exported_docs/moveit2/How-To Guides\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: How-To Guides +URL: https://moveit.picknik.ai/main/doc/how_to_guides/how_to_guides.html +Section: doc/how_to_guides/how_to_guides.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Hybrid Planning\357\203\201.txt" "b/exported_docs/moveit2/Hybrid Planning\357\203\201.txt" new file mode 100644 index 0000000..ed16ac3 --- /dev/null +++ "b/exported_docs/moveit2/Hybrid Planning\357\203\201.txt" @@ -0,0 +1,47 @@ +Title: Hybrid Planning +URL: https://moveit.picknik.ai/main/doc/concepts/hybrid_planning/hybrid_planning.html +Section: index.html +-------------------------------------------------------------------------------- + + +## What is Hybrid Planning? +Hybrid Planning is a term for a motion planning method that combines heterogeneous motion planners to produce more robust or reactive solutions. The general approach is already very established in the Navigation community and successfully implemented in popular projects like navigation2. +MoveIt’s Hybrid Planning architecture combines a pair of global and local planners that run in parallel and recurrently with different planning speeds and problem scopes. +The global planner has the task to solve a global motion planning problem very akin to the planners used in a “Sense-Plan-Act” application. The used planner algorithm should be complete and is therefore assumed to be relatively slow in terms of computation time. Furthermore, the global planner is not required to be real-time safe, meaning that there are no guarantees that the planner finds a solution within a specific deadline. Depending on the planner implementation, the global planner may generate one initial solution or iteratively optimized solutions during the execution. +The local planner is running continuously during execution and produces iterative robot commands for following the global trajectory. In a way, the local planner resembles a controller, only that the architecture allows for solving more complicated problems and constraints. The idea is that the planner is able to reason about the world and to have an internal state. That property makes it very versatile and as it can be used for solving combinations of arbitrary local planning problems, as for example: +In order to enable solving these local problems the local planner must be fast, able to react to sensor feedback and in many cases real-time safe. Also, it should be deterministic in order to avoid jerky or unpredictable motions. +In general, the local planner relies on the reference trajectory produced by the global planner so that it doesn’t get stuck in a local minimum. Since local minima sometimes still can’t be ruled out, it can be required that the global planner is triggered for a replan in order to still reach the desired goal. This behavior requires a certain way to communicate planner events and to process them accordingly. For that purpose the Hybrid Planning architecture allows implementing an event-based logic that can be customized for the specific use case and planner types. +Hybrid Planning can be useful in a broad range of use cases. Most of the applications can be grouped into the following three scenarios. + +## The Hybrid Planning Architecture +The diagram below depicts the fundamental plugin types and ROS interfaces that make up the Hybrid Planning architecture. +The architecture is structured in three ROS component nodes: +The architecture components are designed to be generic and highly customizable. Since the components only interact via ROS 2 message interfaces, it’s very easy to replace implementations of each of the architecture’s components or plugins. The plugin interfaces are designed to be minimal and to abstract from the actual algorithm implementation as much as possible. That allows the developer to fully focus on the isolated logic or solvers without having to implement any parts of the infrastructure. This also allows reusing the same components for different setups or planning problems. + +## Hybrid Planning Manager +This component is “The Brain” of the architecture. Its main purpose is to process HybridPlanner action  requests and to coordinate the motion planning and execution process based on the planning logic plugin. The planning logic is implemented in the PlanningLogic plugin and is event-driven by design. Events are defined by string identifiers and may trigger action calls or cancellations targeting the global or local planners. An example event log for a simple planning logic is shown in the diagram below: +Events are triggered by the Hybrid Planning action request and by both of the global and local planners action feedback messages. In this example, the Hybrid Planning Manager starts the global planner after the hybrid planning request is received. Upon arrival of the global trajectory the local planner is started and when the local planner is finished the Hybrid Planning Manager returns a Hybrid Planning response. +A custom implementation of the Planning Logic plugin supports mapping generic events to available actions provided by the architecture like “Start global planning”, “Stop trajectory execution”, or “Switch to local planner constraint x”. With this, the motion planning behavior becomes highly customizable and adaptable. + +## Global Planner +The Global Planner is the simplest component of the architecture. It provides an action server that processes GlobalPlanner requests. These requests include common MotionPlanRequests, which are processed by the Global Planner plugin. By default, this is simply MoveIt’s planning pipeline, but any kind of planner or even MTC could technically be used here. The planning result is reported using the action feedback and the solution trajectory is published to the Local Planner for further processing. + +## Local Planner +The Local Planner also runs an action server that handles requests from the Hybrid Planning Manager. The action is used for starting and stopping execution and may also configure runtime parameters like constraints or solver types. +The local planner implementation is based on two plugins: +The diagram below shows an example loop cycle of the Local Planner upon action request by the Hybrid Planning Manager: +Each iteration the local planner requests the current planning scene and matches the current robot state within the reference trajectory. If the goal is reached, the local planning action successfully finishes. Otherwise, the current local planning problem is identified based on the current robot state and solved afterwards. Finally, the resulting control commands are published to the robot controller. + +## How does it work? +The runtime behavior of a Hybrid Planner can best be understood by drawing a workflow diagram that visualizes the communication channels and events of the different components. +Below is a diagram that shows the runtime logic of a successful trajectory execution. +The planner is invoked by a hybrid planning request which is also the first event the Hybrid Planning Manager reacts to. +In this example, the planner logic simply runs both planners in sequence. After the initial hybrid planning request, the Hybrid Planning Manager invokes the global planner. +The global planner computes and publishes a trajectory which is received by the Hybrid Planning Manager and the Local Planner Component. +Important to notice is, that the Local Planner Component just processes the new trajectory and does not start executing until it is invoked by the Hybrid Planning Manager. Once requested by the Hybrid Planning Manager, the Local Planner Component starts unwinding the reference trajectory and returns the action response successfully when it reaches the final state. After that, the Hybrid Planning Manager returns a successful HybridPlanningResponse. +Now let’s consider a more difficult scenario where the hybrid planner is designed to avoid an obstacle during execution by replanning. +The animation below shows a simple motion that is being fixed at runtime because of changing collision objects. +Here, the collision object present during the global planning process disappears after the global trajectory is computed. Instead two new collision objects appear that invalidate the initial global trajectory. The local planner detects the imminent collision and pauses the execution until the global planner has provided an updated collision free trajectory. +Below you can see the workflow of the described behavior. +The startup is the same as in the first example, but during unwinding the reference trajectory the local planner detects a collision. Here, the planner logic reacts by re-invoking the global planner. During the calculation of the new global solution, the local planner must prevent the robot from colliding with the collision object i.e. by keeping its current position. After the global planner finishes its calculation, the new global solution is published to the local planner and the local planner’s Trajectory Operator Plugin blends the update into the reference trajectory. Afterwards, the Local Planner Component continues to follow the reference trajectory as the updated solution enables it to steer around the collision object. +If you want to use Hybrid Planning in your application or just want to experiment with it, check out theHybrid Planning Example Tutorial. diff --git "a/exported_docs/moveit2/Kinematics\357\203\201.txt" "b/exported_docs/moveit2/Kinematics\357\203\201.txt" new file mode 100644 index 0000000..f90f4f2 --- /dev/null +++ "b/exported_docs/moveit2/Kinematics\357\203\201.txt" @@ -0,0 +1,26 @@ +Title: Kinematics +URL: https://moveit.picknik.ai/main/doc/concepts/kinematics.html +Section: index.html +-------------------------------------------------------------------------------- + + +## The Kinematics Plugin +MoveIt uses a plugin infrastructure, especially targeted towards allowing users to write their own inverse kinematics algorithms. +Forward kinematics and finding Jacobians is integrated within the RobotState class itself. +The default inverse kinematics plugin for MoveIt is configured using theKDLnumerical Jacobian-based solver. +This plugin is automatically configured by the MoveIt Setup Assistant. + +## Collision Checking +Collision checking in MoveIt is configured inside a Planning Scene using theCollisionWorldobject. +Fortunately, MoveIt is set up so that users never really have to worry about how collision checking is happening. +Collision checking in MoveIt is mainly carried out using theFCLpackage - the primary collision checking library of MoveIt. + +## Collision Objects +MoveIt supports collision checking for different types of objects including: + +## Allowed Collision Matrix (ACM) +Collision checking is a very expensive operation often accounting for close to 90% of the computational expense during motion planning. +TheAllowedCollisionMatrixorACMencodes a binary value corresponding to the need to check for collision between pairs of bodies (which could be on the robot or in the world). +If the value corresponding to two bodies is set totruein the ACM, no collision check between the two bodies will be performed. +The collision checking would not be required if, e.g., the two bodies are always so far away that they can never collide with each other. +Alternatively, the two bodies could be in contact with each other by default, in which case the collision detection should be disabled for the pair in the ACM. diff --git "a/exported_docs/moveit2/Motion Planning\357\203\201.txt" "b/exported_docs/moveit2/Motion Planning\357\203\201.txt" new file mode 100644 index 0000000..80c0b75 --- /dev/null +++ "b/exported_docs/moveit2/Motion Planning\357\203\201.txt" @@ -0,0 +1,61 @@ +Title: Motion Planning +URL: https://moveit.picknik.ai/main/doc/concepts/motion_planning.html +Section: index.html +-------------------------------------------------------------------------------- + + +## The Motion Planning Plugin +MoveIt works with motion planners through aplugin interface. +This allows MoveIt to communicate with and use different motion planners from multiple libraries, making MoveIt easily extensible. The interface to the motion planners is through a ROS action or service (offered by themove_groupnode). +The default motion planners for move_group are configured using OMPL and the MoveIt interface to OMPL by the MoveIt Setup Assistant. +Other planners that are available by default are the Pilz industrial motion planner and CHOMP. + +## The Motion Plan Request +The motion plan request specifies what you would like the motion planner to do. +Typically, you will be asking the motion planner to move an arm to a different location (in joint space) or the end-effector to a new pose. +Collisions are checked for by default (including self-collisions and attached objects). +You can also specify the planner via theplanning_pipelineandplanner_idparameters, and the constraints for the motion planner to check - the inbuilt constraints provided by MoveIt arekinematicconstraints: + +## The Motion Plan Result +Themove_groupnode will generate a desired trajectory in response to your motion plan request. +This trajectory will move the arm (or any group of joints) to the desired location. +Note that the result coming out ofmove_groupis a trajectory and not just a path.move_groupwill use the desired maximum velocities and accelerations (if specified) to generate a trajectory that obeys velocity and acceleration constraints at the joint level. + +## Motion planning adapters +The complete motion planning pipeline chains together a motion planner with other components calledplanning request adapters. +Planning request adapters allow for pre-processing motion plan requests and post-processing motion plan responses. +Pre-processing is useful in several situations, e.g. when a start state for the robot is slightly outside the specified joint limits for the robot. +Post-processing is needed for several other operations, e.g. to convert paths generated for a robot into time-parameterized trajectories. +MoveIt provides a set of default motion planning adapters that each perform a very specific function. + +## CheckStartStateBounds +The fix start state bounds adapter fixes the start state to be within the joint limits specified in the URDF. +The need for this adapter arises in situations where the joint limits for the physical robot are not properly configured. +The robot may then end up in a configuration where one or more of its joints is slightly outside its joint limits. +In this case, the motion planner is unable to plan since it will think that the starting state is outside joint limits. +The “CheckStartStateBounds” planning request adapter will “fix” the start state by moving it to the joint limit. +However, this is obviously not the right solution every time - e.g. where the joint is really outside its joint limits by a large amount. +A parameter for the adapter specifies how much the joint can be outside its limits for it to be “fixable”. + +## ValidateWorkspaceBounds +The fix workspace bounds adapter will specify a default workspace for planning: a cube of size 10 m x 10 m x 10 m. +This workspace will only be specified if the planning request to the planner does not have these fields filled in. + +## CheckStartStateCollision +The fix start state collision adapter will attempt to sample a new collision-free configuration near a specified configuration (in collision) by perturbing the joint values by a small amount. +The amount that it will perturb the values by is specified by thejiggle_fractionparameter that controls the perturbation as a percentage of the total range of motion for the joint. +The other parameter for this adapter specifies how many random perturbations the adapter will sample before giving up. + +## AddTimeParameterization +The motion planners will typically generate “kinematic paths”, i.e., paths that do not obey any velocity or acceleration constraints and are not time parameterized. +This adapter will “time parameterize” the motion plans by applying velocity and acceleration constraints. + +## ResolveConstraintFrames +Goal constraints can be set using subframes (e.g. a pose goal in the framecup/handle, wherehandleis a subframe on the objectcup). +This adapter changes the frame of constraints to an object or robot frame (e.g.cup). + +## OMPL +OMPL (Open Motion Planning Library) is an open-source motion planning library that primarily implements randomized motion planners. +MoveIt integrates directly with OMPL and uses the motion planners from that library as its primary/default set of planners. +The planners in OMPL are abstract; i.e. OMPL has no concept of a robot. +Instead, MoveIt configures OMPL and provides the back-end for OMPL to work with problems in Robotics. diff --git "a/exported_docs/moveit2/MoveIt 2 Documentation\357\203\201.txt" "b/exported_docs/moveit2/MoveIt 2 Documentation\357\203\201.txt" new file mode 100644 index 0000000..343503d --- /dev/null +++ "b/exported_docs/moveit2/MoveIt 2 Documentation\357\203\201.txt" @@ -0,0 +1,18 @@ +Title: MoveIt 2 Documentation +URL: https://moveit.picknik.ai/main/index.html +Section: index.html +-------------------------------------------------------------------------------- + + +## How-To Use This Website + + +## Table Of Contents + + +## Attribution +Some major past contributors to the MoveIt tutorials are listed in chronological order: Sachin Chitta, Dave Hershberger, Acorn Pooley, Dave Coleman, Michael Goerner, Francisco Suarez, Mike Lautman, Tyler Weaver, David Lu!!, Vatan Tezer, and Andy Zelenak. These are just some of the46+ Contributors over the yearswho have a big impact on this documentation. +Help us improve these docs and we’ll be happy to include you here also! + +## Corporate Sponsorship + diff --git "a/exported_docs/moveit2/MoveIt Quickstart in RViz\357\203\201.txt" "b/exported_docs/moveit2/MoveIt Quickstart in RViz\357\203\201.txt" new file mode 100644 index 0000000..1376d0e --- /dev/null +++ "b/exported_docs/moveit2/MoveIt Quickstart in RViz\357\203\201.txt" @@ -0,0 +1,93 @@ +Title: MoveIt Quickstart in RViz +URL: https://moveit.picknik.ai/main/doc/tutorials/quickstart_in_rviz/quickstart_in_rviz_tutorial.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Getting Started +If you haven’t already done so, make sure you’ve completed the steps inGetting Startedor ourDocker Guide. +If you followed the Docker Guide, also follow theCreate A Colcon Workspace and Download Tutorialsguide onwards to set up the tutorials. + +## Step 1: Launch the Demo and Configure the Plugin + + +## Step 2: Play with the Visualized Robots +There are four different overlapping visualizations: +The display states for each of these visualizations can be toggled on and off using checkboxes: + +## Step 3: Interact with the Kinova Gen 3 +For the next steps we will want only the scene robot, start state and goal state: +There should now be two interactive markers. One marker corresponding to the orange colored arm will be used to set the “Goal State” for motion planning and the other marker corresponding to a green colored arm are used to set the “Start State” for motion planning. If you don’t see the interactive markers pressInteractin the top menu of RViz (Note: some tools may be hidden, press“+”in the top menu to add theInteracttool as shown below). +You should now be able to use these markers to drag the arm around and change its orientation. Try it! + +## Moving into collision +For this section, hide the planned path and the goal state: +Now, only the Start State (the green colored arm) should be visible. Try to move the arm into a configuration where two of its links are in collision with each other. (If you find this difficult, make sure the “Use Collision-Aware IK” checkbox under the Planning tab of the MotionPlanning plugin is un-checked.) Once you do this, the links that are in collision will turn red. +Now, check the “Use Collision-Aware IK” checkbox, and try again to move two of the links into collision with each other. When the checkbox is ticked, the IK solver will keep attempting to find a collision-free solution for the desired end-effector pose. When it is not checked, the solver will allow collisions to happen in the solution. The links in collision will always still be visualized in red, regardless of the state of the checkbox. + +## Moving out of Reachable Workspace +Note what happens when you try to move an end-effector out of its reachable workspace. +Before moving onto the next section, re-enable the planned path and the goal state: + +## Moving Joints or in Null Space +You can use theJointstab to move single joints and the redundant joints of 7-DOF robots. Try moving the “null space exploration” slider as shown in the animation below. + +## Step 4: Use Motion Planning with the Kinova Gen 3 + + +## Introspecting Trajectory Waypoints +You can visually introspect trajectories point by point in RViz. +Note: Once you placed your end-effector to a new goal, be sure to runPlanbefore runningPlay– otherwise you’ll see the waypoints for the previous goal if available. + +## Plan Cartesian motions +If the “Use Cartesian Path” checkbox is activated, the robot will attempt to move the end effector linearly in cartesian space. + +## Executing Trajectories, Adjusting Speed +Clicking “Plan & Execute” or “Execute” after a successful plan will send the trajectory to the robot - in this tutorial, since you usedkinova_demo.launch, the robot is only simulated. +Initially, the default velocity and acceleration are scaled to 10% (0.1) of the robot’s maximum. You can change these scaling factors in the Planning tab shown below, or change these default values in themoveit_configof your robot (injoint_limits.yaml). + +## Next Steps + + +## RViz Visual Tools +Many of the tutorials usemoveit_visual_toolsto step through a demo. Before continuing on to the next tutorials it is a good idea to enable theRvizVisualToolsGui. +From “Panels” menu, select “Add New Panels”. From the menu, select “RvizVisualToolsGui” and click OK. You’ll see the new panel added to RViz. + +## Saving Your Configuration +RViz enables you to save your configuration underFile->SaveConfig. You should do this before continuing on to the next tutorials. If you choose to save your configuration under a new name, you can useFile->SaveConfigAsand refer to your configuration file using: +Replaceyour_rviz_config.rvizwith the name of the file you saved tomoveit2_tutorials/doc/tutorials/quickstart_in_rviz/launch/and build the workspace so it can be found. + +## Next Tutorial +InYour First MoveIt Project, you will create a C++ program using MoveIt to plan and execute moves. + +Code Examples: + +Language: unknown +``` +ros2 +launch +moveit2_tutorials +demo +. +launch +. +py +``` + +Language: unknown +File: File->SaveConfigAs +``` +ros2 +launch +moveit2_tutorials +demo +. +launch +. +py +rviz_config +:= +your_rviz_config +. +rviz +``` diff --git "a/exported_docs/moveit2/MoveIt Task Constructor\357\203\201.txt" "b/exported_docs/moveit2/MoveIt Task Constructor\357\203\201.txt" new file mode 100644 index 0000000..9975a89 --- /dev/null +++ "b/exported_docs/moveit2/MoveIt Task Constructor\357\203\201.txt" @@ -0,0 +1,328 @@ +Title: MoveIt Task Constructor +URL: https://moveit.picknik.ai/main/doc/concepts/moveit_task_constructor/moveit_task_constructor.html +Section: index.html +-------------------------------------------------------------------------------- + + +## What is MoveIt Task Constructor? + + +## MTC Stages +There are three possible stages relating to the result flow: + +## Generator Stage + + +## Propagating Stage + + +## Connecting Stage + + +## Wrapper + + +## MTC Containers +Currently available containers: + +## Serial Container + + +## Parallel Container +Parallel containers combine a set of stages to allow planning alternate solutions. + +## Initializing a MTC Task +The top-level planning problem is specified as a MTC Task and the subproblems which are specified by Stages are added to the MTC task object. + +## Adding containers and stages to a MTC Task +Adding a stage to MTC task +Containers derive from Stage and hence containers can be added to MTC task similarly + +## Setting planning solvers +Stages that do motion planning need solver information. +Solvers available in MTC +Code Example on how to initialize the solver +These solvers will be passed into stages likeMoveTo,MoveRelative, andConnect. + +## Setting Properties + + +## Cost calculator for Stages +CostTerm is the basic interface to compute costs for solutions for MTC stages. +CostTerm implementations available in MTC +Example code on how to set CostTerm usingLambdaCostTerm +All stages provided by MTC have default cost terms. Stages which produce trajectories as solutions usually use path length to calculate cost. + +## Planning and Executing a MTC Task +Planning an MTC task will return aMoveItErrorCode. +Referhereto identity the different error types. +If planning succeeds, you can expect the plan function to returnmoveit_msgs::msg::MoveItErrorCodes::SUCCESS. +After planning, extract the first successful solution and pass it to the execute function. This will create anexecute_task_solutionaction client. +The action server resides in theexecute_task_solution_capabilityplugin provided by MTC. +The plugin extendsMoveGroupCapability. It constructs aMotionPlanRequestfrom the MTC solution and uses MoveIt’sPlanExecutionto actuate the robot. + +## Links to Additional Information +Here is atutorialon how to create a Pick and Place pipeline using MTC. +The links listed below contain more information on stages and containers provided by MTC + +Code Examples: + +Language: unknown +File: GeneratePose +``` +auto +node += +std +:: +make_shared +< +rclcpp +:: +Node +> +(); +auto +task += +std +:: +make_unique +< +moveit +:: +task_constructor +:: +Task +> +(); +task +-> +loadRobotModel +( +node +); +// Set controllers used to execute robot motion. If not set, MoveIt has controller discovery logic. +task +-> +setProperty +( +"trajectory_execution_info" +, +"joint_trajectory_controller gripper_controller" +); +``` + +Language: unknown +File: GeneratePose +``` +auto +current_state += +std +:: +make_unique +< +moveit +:: +task_constructor +:: +stages +:: +CurrentState +> +( +"current_state" +); +task +-> +add +( +std +:: +move +( +current_state +)); +``` + +Language: unknown +File: GeneratePose +``` +auto +container += +std +:: +make_unique +< +moveit +:: +task_constructor +:: +SerialContainer +> +( +"Pick Object" +); +// TODO: Add stages to the container before adding the container to MTC task +task +-> +add +( +std +:: +move +( +container +)); +``` + +Language: unknown +File: CartesianPath +``` +const +auto +mtc_pipeline_planner += +std +:: +make_shared +< +moveit +:: +task_constructor +:: +solvers +:: +PipelinePlanner +> +( +node +, +"ompl" +, +"RRTConnectkConfigDefault" +); +const +auto +mtc_joint_interpolation_planner += +std +:: +make_shared +< +moveit +:: +task_constructor +:: +solvers +:: +JointInterpolationPlanner +> +(); +const +auto +mtc_cartesian_planner += +std +:: +make_shared +< +moveit +:: +task_constructor +:: +solvers +:: +CartesianPath +> +(); +``` + +Language: unknown +File: Connect +``` +void +setProperty +( +const +std +:: +string +& +name +, +const +boost +:: +any +& +value +); +``` + +Language: unknown +File: LambdaCostTerm +``` +stage +-> +setCostTerm +( +moveit +:: +task_constructor +:: +LambdaCostTerm +( +[]( +const +moveit +:: +task_constructor +:: +SubTrajectory +& +traj +) +{ +return +100 +* +traj +. +cost +(); +})); +``` + +Language: unknown +File: moveit_msgs::msg::MoveItErrorCodes::SUCCESS +``` +auto +error_code += +task +. +plan +() +``` + +Language: unknown +File: PlanExecution +``` +auto +result += +task +. +execute +( +* +task +. +solutions +(). +front +()); +``` diff --git "a/exported_docs/moveit2/Pick and Place with MoveIt Task Constructor\357\203\201.txt" "b/exported_docs/moveit2/Pick and Place with MoveIt Task Constructor\357\203\201.txt" new file mode 100644 index 0000000..9fc1c2f --- /dev/null +++ "b/exported_docs/moveit2/Pick and Place with MoveIt Task Constructor\357\203\201.txt" @@ -0,0 +1,3440 @@ +Title: Pick and Place with MoveIt Task Constructor +URL: https://moveit.picknik.ai/main/doc/tutorials/pick_and_place_with_moveit_task_constructor/pick_and_place_with_moveit_task_constructor.html +Section: index.html +-------------------------------------------------------------------------------- + + +## 1 Basic Concepts +The fundamental idea of MTC is that complex motion planning problems can be composed into a set of simpler subproblems. +The top-level planning problem is specified as aTaskwhile all subproblems are specified byStages. +Stages can be arranged in any arbitrary order and hierarchy only limited by the individual stages types. +The order in which stages can be arranged is restricted by the direction in which results are passed. +There are three possible stages relating to the result flow: generator, propagator, and connector stages: +Generatorscompute their results independently of their neighbor stages and pass them in both directions, backwards and forwards. +An example is an IK sampler for geometric poses where approaching and departing motions (neighbor stages) depend on the solution. +Propagatorsreceive the result of one neighbor stage, solve a subproblem and then propagate their result to the neighbor on the opposite site. +Depending on the implementation, propagating stages can pass solutions forward, backward or in both directions separately. +An example is a stage that computes a Cartesian path based on either a start or a goal state. +Connectorsdo not propagate any results, but rather attempt to bridge the gap between the resulting states of both neighbors. +An example is the computation of a free-motion plan from one given state to another. +Additional to the order types, there are different hierarchy types allowing to encapsulate subordinate stages. +Stages without subordinate stages are calledprimitive stages, higher-level stages are calledcontainer stages. +There are three container types: +Wrappersencapsulate a single subordinate stage and modify or filter the results. +For example, a filter stage that only accepts solutions of its child stage that satisfy a certain constraint can be realized as a wrapper. +Another standard use of this type includes the IK wrapper stage, which generates inverse kinematics solutions based on planning scenes annotated with a pose target property. +Serial Containershold a sequence of subordinate stages and only consider end-to-end solutions as results. +An example is a picking motion that consists of a sequence of coherent steps. +Parallel Containerscombine set of subordinate stages and can be used for passing the best of alternative results, running fallback solvers or for merging multiple independent solutions. +Examples are running alternative planners for a free-motion plan, picking objects with the right hand or with the left hand as a fallback, or moving the arm and opening the gripper at the same time. +Stages not only support solving motion planning problems. +They can also be used for all kinds of state transitions, as for instance modifying the planning scene. +Combined with the possibility of using class inheritance it is possible to construct very complex behavior while only relying on a well-structured set of primitive stages. +More detailed information on MTC can be found in theMoveIt Task Constructor concepts page + +## 2 Getting Started +If you haven’t already done so, make sure you’ve completed the steps inGetting Started. +Move into your colcon workspace and pull the MoveIt Task Constructor source, wherecan be e.g.humblefor ROS Humble, orros2for the latest version compatible with MoveIt 2main: +Install missing packages with rosdep: +Build the workspace: + +## 3 Trying It Out +The MoveIt Task Constructor package contains several basic examples and a pick-and-place demo. +For all demos you should launch the basic environment: +Subsequently, you can run the individual demos: +On the right side you should see theMotion Planning Taskspanel outlining the hierarchical stage structure of the tasks. +When you select a particular stage, the list of successful and failed solutions will be +shown in the right-most window. Selecting one of those solutions will start its visualization. + +## 4 Setting up a Project with MoveIt Task Constructor +This section walks through the steps required to build a simple task with MoveIt Task Constructor. + +## 4.1 Create a New Package +Create a new package with the following command: +This will create a new package and folder calledmtc_tutorialwith a dependency onmoveit_task_constructor_coreas well as a hello world example insrc/mtc_node. + +## 4.2 The Code +Openmtc_node.cppin your editor of choice, and paste in the following code. + +## 4.3 Code Breakdown +The top of the code includes the ROS and MoveIt Libraries that this package uses. +The next line gets a logger for our new node. We also create a namespace alias formoveit::task_constructorfor convenience. +We start by defining a class that will contain the main MoveIt Task Constructor functionality. We also declare the MoveIt Task Constructor task object as a member variable for our class: this isn’t strictly necessary for a given application, but it helps save the task for later visualization purposes. We will explore each function individually below. +These lines initialize the node with specified options (it is the constructor of ourMTCTaskNodeclass). +These next lines define a getter function to get the node base interface, which will be used for the executor later. +This class method is used to set up the planning scene that is used in the example. It creates a cylinder with dimensions specified byobject.primitives[0].dimensionsand position specified bypose.position.xandpose.position.y. +You can try changing these numbers to resize and move the cylinder around. If we move the cylinder out of the robot’s reach, planning will fail. +This function interfaces with the MoveIt Task Constructor task object. It first creates a task, which includes setting some properties and adding stages. This will be discussed further in thecreateTaskfunction definition. Next,task.init()initializes the task andtask.plan(5)generates a plan, stopping after 5 successful plans are found. The next line publishes the solution to be visualized in RViz - this line can be removed if you don’t care for visualization. Finally,task.execute()executes the plan. Execution occurs via an action server interface with the RViz plugin. +As mentioned above, this function creates a MoveIt Task Constructor object and sets some initial properties. In this case, we set the task name to “demo_task”, load the robot model, define the names of some useful frames, and set those frame names as properties of the task withtask.setProperty(property_name,value). The next few code blocks will fill out this function body. +Now, we add an example stage to the node. The first line setscurrent_state_ptrtonullptr; this creates a pointer to a stage such that we can reuse stage information in specific scenarios. This line is not used at this moment, but will be used later when more stages are added to the task. Next, we make acurrent_statestage (a generator stage) and add it to our task - this starts the robot off in its current state. Now that we’ve created theCurrentStatestage, we save a pointer to it in thecurrent_state_ptrfor later use. +Solvers are used to define the type of robot motion. MoveIt Task Constructor has three options for solvers: +Feel free to try out the different solvers and see how the robot motion changes. For the first stage we will use the Cartesian planner, which requires the following properties to be set: +Now that we added in the planners, we can add a stage that will move the robot. +The following lines use aMoveTostage (a propagator stage). Since opening the hand is a relatively simple movement, we can use the joint interpolation planner. +This stage plans a move to the “open hand” pose, which is a named pose defined in theSRDFfor the Panda robot. +We return the task and finish with thecreateTask()function. +Finally, we havemain: the following lines create a node using the class defined above, and calls the class methods to set up and execute a basic MTC task. In this example, we do not cancel the executor once the task has finished executing to keep the node alive to inspect the solutions in RViz. + +## 5 Running the Demo + + +## 5.1 Launch Files +We will need a launch file to launch themove_group,ros2_control,static_tf,robot_state_publisher, andrviznodes that provide us the environment to run the demo. The one we will use for this example can be foundhere. +To run the MoveIt Task Constructor node, we will use a second launch file to start themtc_tutorialexecutable with the proper parameters. Here we can load URDF, SRDF, and OMPL parameters, or use MoveIt Configs Utils to do so. Your launch file should look something like the one found in this tutorial packagehere(pay close attention to thepackageandexecutablearguments below as they are different from the launch file linked) : +Save a launch file aspick_place_demo.launch.pyor download one to the package’s launch directory. Make sure to edit theCMakeLists.txtso it includes the launch folder by adding the following lines: +Now we can build and source the colcon workspace. +Start by launching the first launch file. If you want to use the one provided by the tutorials: +RViz will now load. If you’re using your own launch file and haven’t included an rviz configsuch as this, you will need to configure RViz before you see anything displayed. If you’re using the launch file from the tutorials package, RViz will already be configured for you and you can jump to the end of the next section. + +## 5.2 RViz Configuration +If you are not using the RViz configuration provided, we’ll have to make some changes to the RViz configuration to see your robot and the MoveIt Task Constructor solutions. First, start RViz. The following steps will cover how to set up RViz for MoveIt Task Constructor solution visualization. +You should see the panda arm in the main view with Motion Planning Tasks display open in the bottom left and nothing in it. Your MTC task will show up in this panel once you launch themtc_tutorialnode. If you’re usingmtc_demo.launch.pyfrom the tutorials, jump back in here. + +## 5.3 Launching the Demo +Launch themtc_tutorialnode with +You should see the arm execute the task with the single stage to open the hand, with the cylinder in green in front of it. It should look something like this: +If you haven’t made your own package, but still want to see what this looks like, you can launch this file from the tutorials: + +## 6 Adding Stages +So far, we’ve walked through creating and executing a simple task, which runs but does not do much. Now, we will start adding the pick-and-place stages to the task. The image below shows an outline of the stages we will use in our task. +We will start adding stages after our existing open hand stage. Openmtc_node.cppand locate the following lines: + +## 6.1 Pick Stages +We need to move the arm to a position where we can pick up our object. This is done with aConnectstage, which as its name implies, is a Connector stage. This means that it tries to bridge between the results of the stage before and after it. This stage is initialized with a name,move_to_pick, and aGroupPlannerVectorthat specifies the planning group and the planner. We then set a timeout for the stage, set the properties for the stage, and add it to our task. +Next, we create a pointer to a MoveIt Task Constructor stage object, and set it tonullptrfor now. Later, we will use this to save a stage. +This next block of code creates aSerialContainer. +This is a container that can be added to our task and can hold several substages. +In this case, we create a serial container that will contain the stages relevant to the picking action. +Instead of adding the stages to the task, we will add the relevant stages to the serial container. We useexposeTo()to declare the task properties from the parent task in the new serial container, and useconfigureInitFrom()to initialize them. +This allows the contained stages to access these properties. +We then create a stage to approach the object. This stage is aMoveRelativestage, which allows us to specify a relative movement from our current position.MoveRelativeis a propagator stage: it receives the solution from its neighbouring stages and propagates it to the next or previous stage. Usingcartesian_plannerfinds a solution that involves moving the end effector in a straight line. We set the properties, and set the minimum and maximum distance to move. Now we create aVector3Stampedmessage to indicate the direction we want to move - in this case, in the Z direction from the hand frame. Finally, we add this stage to our serial container +Now, create a stage to generate the grasp pose. +This is a generator stage, so it computes its results without regard to the stages before and after it. +The first stage,CurrentStateis a generator stage as well - to connect the first stage and this stage, a connecting stage must be used, which we already created above. +This code sets the stage properties, sets the pose before grasping, the angle delta, and the monitored stage. +Angle delta is a property of theGenerateGraspPosestage that is used to determine the number of poses to generate; when generating solutions, MoveIt Task Constructor will try to grasp the object from many different orientations, with the difference between the orientations specified by the angle delta. The smaller the delta, the closer together the grasp orientations will be. When defining the current stage, we setcurrent_state_ptr, which is now used to forward information about the object pose and shape to the inverse kinematics solver. +This stage won’t be directly added to the serial container like previously, as we still need to do inverse kinematics on the poses it generates. +Before we compute inverse kinematics for the poses generated above, we first need to define the frame. This can be done with aPoseStampedmessage fromgeometry_msgsor in this case, we define the transform using Eigen transformation matrix and the name of the relevant link. Here, we define the transformation matrix. +Now, we create theComputeIKstage, and give it the namegenerateposeIKas well as thegenerategraspposestage defined above. Some robots have multiple inverse kinematics solutions for a given pose - we set the limit on the amount of solutions to solve for up to 8. We also set the minimum solution distance, which is a threshold on how different solutions must be: if the joint positions in a solution are too similar to a previous solution, it will be marked as invalid. Next, we configure some additional properties, and add theComputeIKstage to the serial container. +To pick up the object, we must allow collision between the hand and the object. This can be done with aModifyPlanningScenestage. TheallowCollisionsfunction lets us specify which collisions to disable.allowCollisionscan be used with a container of names, so we can usegetLinkModelNamesWithCollisionGeometryto get all the names of links with collision geometry in the hand group. +With collisions allowed, we now can close the hand. This is done with aMoveTostage, similarly to theopenhandstage from above, except moving to thecloseposition as defined in the SRDF. +We now use aModifyPlanningScenestage again, this time to attach the object to the hand usingattachObject. Similarly to what we did with thecurrent_state_ptr, we get a pointer to this stage for later use when generating the place pose for the object. +Next, we lift the object with aMoveRelativestage, similarly to theapproach_objectstage. +With this, we have all the stages needed to pick the object. Now, we add the serial container (with all its substages) to the task. If you build the package as-is, you can see the robot plan to pick up the object. +To test out the newly created stage, build the code and execute: + +## 6.2 Place Stages +Now that the stages that define the pick are complete, we move on to defining the stages for placing the object. Picking up where we left off, we add aConnectstage to connect the two, as we will soon be using a generator stage to generate the pose for placing the object. +We also create a serial container for the place stages. This is done similarly to the pick serial container. +The next stages will be added to the serial container rather than the task. +This next stage generates the poses used to place the object and compute the inverse kinematics for those poses - it is somewhat similar to thegenerategraspposestage from the pick serial container. +We start by creating a stage to generate the poses and inheriting the task properties. +We specify the pose where we want to place the object with aPoseStampedmessage fromgeometry_msgs- in this case, we choosey=0.5in the"object"frame. +We then pass the target pose to the stage withsetPose. +Next, we usesetMonitoredStageand pass it the pointer to theattach_objectstage from earlier. +This allows the stage to know how the object is attached. +We then create aComputeIKstage and pass it ourGeneratePlacePosestage - the rest follows the same logic as above with the pick stages. +Now that we’re ready to place the object, we open the hand withMoveTostage and the joint interpolation planner. +We also can re-enable collisions with the object now that we no longer need to hold it. +This is done usingallowCollisionsalmost exactly the same way as disabling collisions, except setting the last argument tofalserather thantrue. +Now, we can detach the object usingdetachObject. +We retreat from the object using aMoveRelativestage, which is done similarly to theapproachobjectandliftobjectstages. +We finish our place serial container and add it to the task. +The final step is to return home: we use aMoveTostage and pass it the goal pose ofready, which is a pose defined in the Panda SRDF. +All these stages should be added above these lines. +Congratulations! You’ve now defined a pick and place task using MoveIt Task Constructor! To try it out, build the code and execute: + +## 7 Further Discussion +The task with each comprising stage is shown in the Motion Planning Tasks pane. Click on a stage and additional information about the stage will show up to the right. The right pane shows different solutions as well as their associated costs. Depending on the stage type and the robot configuration, there may only be one solution shown. +Click one of the solution costs to see an animation of the robot following the plan for that stage. Click the “Exec” button in the upper-right portion of the pane to execute the motion. +To run the complete MoveIt Task Constructor example included with the MoveIt tutorials: +And in a second terminal: + +## 7.1 Debugging Information Printed to the Terminal +When running MTC, it prints a diagram like this to terminal: +This example^ shows two stages. The first stage (“initial_state”) is aCurrentStatetype of stage, which initializes aPlanningSceneand captures any collision objects that are present at that moment. +A pointer to this stage can be used to retrieve the state of the robot. +SinceCurrentStateinherits fromGenerator, it propagates solutions both forward and backward. +This is denoted by the arrows in both directions. +The second stage (“move_to_home”) is aMoveTotype of stage. It inherits its propagation direction from the previous stage, so both arrows point forward. The0’s indicate that this stage failed completely. From left to right, the0’s mean: +In this case, we could tell that “move_to_home” was the root cause of the failure. The problem was a home state that was in collision. Defining a new, collision-free home position fixed the issue. + +## 7.2 Stages +Information about individual stages can be retrieved from the task. For example, here we retrieve the unique ID for a stage: +ACurrentStatetype stage does not just retrieve the current state of the robot. +It also initializes aPlanningSceneobject, capturing any collision objects that are present at that moment. +MTC stages can be propagated in forward and backward order. +You can easily check which direction a stage propagates by the arrow in the RViz GUI. +When propagating backwards, the logic of many operations is reversed. +For example, to allow collisions with an object in aModifyPlanningScenestage, you would callallowCollisions(false)rather thanallowCollisions(true). There is a discussion to be readhere. + +Code Examples: + +Language: unknown +File: main +``` +cd +~/ +ws_moveit +/ +src +git +clone +- +b +< +branch +> +https +: +// +github +. +com +/ +moveit +/ +moveit_task_constructor +. +git +``` + +Language: unknown +File: main +``` +rosdep install --from-paths . --ignore-src --rosdistro $ROS_DISTRO + +``` + +Language: unknown +File: main +``` +cd +~/ +ws_moveit +colcon +build +-- +mixin +release +``` + +Language: unknown +File: main +``` +ros2 +launch +moveit_task_constructor_demo +demo +. +launch +. +py +``` + +Language: unknown +File: main +``` +ros2 +launch +moveit_task_constructor_demo +run +. +launch +. +py +exe +:= +cartesian +ros2 +launch +moveit_task_constructor_demo +run +. +launch +. +py +exe +:= +modular +ros2 +launch +moveit_task_constructor_demo +run +. +launch +. +py +exe +:= +pick_place_demo +``` + +Language: unknown +File: main +``` +ros2 +pkg +create + \ + +-- +build +- +type +ament_cmake + \ + +-- +dependencies +moveit_task_constructor_core +rclcpp + \ + +-- +node +- +name +mtc_node +mtc_tutorial +``` + +Language: unknown +File: mtc_node.cpp +``` +#include + +#include + +#include + +#include + +#include + +#include + +#if __has_include() +#include + +#else +#include + +#endif +#if __has_include() +#include + +#else +#include + +#endif +static +const +rclcpp +:: +Logger +LOGGER += +rclcpp +:: +get_logger +( +"mtc_tutorial" +); +namespace +mtc += +moveit +:: +task_constructor +; +class +MTCTaskNode +{ +public +: +MTCTaskNode +( +const +rclcpp +:: +NodeOptions +& +options +); +rclcpp +:: +node_interfaces +:: +NodeBaseInterface +:: +SharedPtr +getNodeBaseInterface +(); +void +doTask +(); +void +setupPlanningScene +(); +private +: +// Compose an MTC task from a series of stages. +mtc +:: +Task +createTask +(); +mtc +:: +Task +task_ +; +rclcpp +:: +Node +:: +SharedPtr +node_ +; +}; +MTCTaskNode +:: +MTCTaskNode +( +const +rclcpp +:: +NodeOptions +& +options +) +: +node_ +{ +std +:: +make_shared +< +rclcpp +:: +Node +> +( +"mtc_node" +, +options +) +} +{ +} +rclcpp +:: +node_interfaces +:: +NodeBaseInterface +:: +SharedPtr +MTCTaskNode +:: +getNodeBaseInterface +() +{ +return +node_ +-> +get_node_base_interface +(); +} +void +MTCTaskNode +:: +setupPlanningScene +() +{ +moveit_msgs +:: +msg +:: +CollisionObject +object +; +object +. +id += +"object" +; +object +. +header +. +frame_id += +"world" +; +object +. +primitives +. +resize +( +1 +); +object +. +primitives +[ +0 +]. +type += +shape_msgs +:: +msg +:: +SolidPrimitive +:: +CYLINDER +; +object +. +primitives +[ +0 +]. +dimensions += +{ +0.1 +, +0.02 +}; +geometry_msgs +:: +msg +:: +Pose +pose +; +pose +. +position +. +x += +0.5 +; +pose +. +position +. +y += +-0.25 +; +pose +. +orientation +. +w += +1.0 +; +object +. +pose += +pose +; +moveit +:: +planning_interface +:: +PlanningSceneInterface +psi +; +psi +. +applyCollisionObject +( +object +); +} +void +MTCTaskNode +:: +doTask +() +{ +task_ += +createTask +(); +try +{ +task_ +. +init +(); +} +catch +( +mtc +:: +InitStageException +& +e +) +{ +RCLCPP_ERROR_STREAM +( +LOGGER +, +e +); +return +; +} +if +( +! +task_ +. +plan +( +5 +)) +{ +RCLCPP_ERROR_STREAM +( +LOGGER +, +"Task planning failed" +); +return +; +} +task_ +. +introspection +(). +publishSolution +( +* +task_ +. +solutions +(). +front +()); +auto +result += +task_ +. +execute +( +* +task_ +. +solutions +(). +front +()); +if +( +result +. +val +!= +moveit_msgs +:: +msg +:: +MoveItErrorCodes +:: +SUCCESS +) +{ +RCLCPP_ERROR_STREAM +( +LOGGER +, +"Task execution failed" +); +return +; +} +return +; +} +mtc +:: +Task +MTCTaskNode +:: +createTask +() +{ +mtc +:: +Task +task +; +task +. +stages +() +-> +setName +( +"demo task" +); +task +. +loadRobotModel +( +node_ +); +const +auto +& +arm_group_name += +"panda_arm" +; +const +auto +& +hand_group_name += +"hand" +; +const +auto +& +hand_frame += +"panda_hand" +; +// Set task properties +task +. +setProperty +( +"group" +, +arm_group_name +); +task +. +setProperty +( +"eef" +, +hand_group_name +); +task +. +setProperty +( +"ik_frame" +, +hand_frame +); +// Disable warnings for this line, as it's a variable that's set but not used in this example +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +mtc +:: +Stage +* +current_state_ptr += +nullptr +; +// Forward current_state on to grasp pose generator +#pragma GCC diagnostic pop +auto +stage_state_current += +std +:: +make_unique +< +mtc +:: +stages +:: +CurrentState +> +( +"current" +); +current_state_ptr += +stage_state_current +. +get +(); +task +. +add +( +std +:: +move +( +stage_state_current +)); +auto +sampling_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +PipelinePlanner +> +( +node_ +); +auto +interpolation_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +JointInterpolationPlanner +> +(); +auto +cartesian_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +CartesianPath +> +(); +cartesian_planner +-> +setMaxVelocityScalingFactor +( +1.0 +); +cartesian_planner +-> +setMaxAccelerationScalingFactor +( +1.0 +); +cartesian_planner +-> +setStepSize +( +.01 +); +auto +stage_open_hand += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveTo +> +( +"open hand" +, +interpolation_planner +); +stage_open_hand +-> +setGroup +( +hand_group_name +); +stage_open_hand +-> +setGoal +( +"open" +); +task +. +add +( +std +:: +move +( +stage_open_hand +)); +return +task +; +} +int +main +( +int +argc +, +char +** +argv +) +{ +rclcpp +:: +init +( +argc +, +argv +); +rclcpp +:: +NodeOptions +options +; +options +. +automatically_declare_parameters_from_overrides +( +true +); +auto +mtc_task_node += +std +:: +make_shared +< +MTCTaskNode +> +( +options +); +rclcpp +:: +executors +:: +MultiThreadedExecutor +executor +; +auto +spin_thread += +std +:: +make_unique +< +std +:: +thread +> +([ +& +executor +, +& +mtc_task_node +]() +{ +executor +. +add_node +( +mtc_task_node +-> +getNodeBaseInterface +()); +executor +. +spin +(); +executor +. +remove_node +( +mtc_task_node +-> +getNodeBaseInterface +()); +}); +mtc_task_node +-> +setupPlanningScene +(); +mtc_task_node +-> +doTask +(); +spin_thread +-> +join +(); +rclcpp +:: +shutdown +(); +return +0 +; +} +``` + +Language: unknown +File: tf2_eigen/tf2_eigen.hpp +``` +#include + +#include + +#include + +#include + +#include + +#include + +#if __has_include() +#include + +#else +#include + +#endif +#if __has_include() +#include + +#else +#include + +#endif +``` + +Language: unknown +File: moveit::task_constructor +``` +static +const +rclcpp +:: +Logger +LOGGER += +rclcpp +:: +get_logger +( +"mtc_tutorial" +); +namespace +mtc += +moveit +:: +task_constructor +; +``` + +Language: unknown +File: moveit::task_constructor +``` +class +MTCTaskNode +{ +public +: +MTCTaskNode +( +const +rclcpp +:: +NodeOptions +& +options +); +rclcpp +:: +node_interfaces +:: +NodeBaseInterface +:: +SharedPtr +getNodeBaseInterface +(); +void +doTask +(); +void +setupPlanningScene +(); +private +: +// Compose an MTC task from a series of stages. +mtc +:: +Task +createTask +(); +mtc +:: +Task +task_ +; +rclcpp +:: +Node +:: +SharedPtr +node_ +; +}; +``` + +Language: unknown +File: MTCTaskNode +``` +MTCTaskNode +:: +MTCTaskNode +( +const +rclcpp +:: +NodeOptions +& +options +) +: +node_ +{ +std +:: +make_shared +< +rclcpp +:: +Node +> +( +"mtc_node" +, +options +) +} +{ +} +``` + +Language: unknown +File: MTCTaskNode +``` +rclcpp +:: +node_interfaces +:: +NodeBaseInterface +:: +SharedPtr +MTCTaskNode::getNodeBaseInterface +() +{ +return +node_ +-> +get_node_base_interface +(); +} +``` + +Language: unknown +File: pose.position.y +``` +void +MTCTaskNode::setupPlanningScene +() +{ +moveit_msgs +:: +msg +:: +CollisionObject +object +; +object +. +id += +"object" +; +object +. +header +. +frame_id += +"world" +; +object +. +primitives +. +resize +( +1 +); +object +. +primitives +[ +0 +]. +type += +shape_msgs +:: +msg +:: +SolidPrimitive +:: +CYLINDER +; +object +. +primitives +[ +0 +]. +dimensions += +{ +0.1 +, +0.02 +}; +geometry_msgs +:: +msg +:: +Pose +pose +; +pose +. +position +. +x += +0.5 +; +pose +. +position +. +y += +-0.25 +; +object +. +pose += +pose +; +moveit +:: +planning_interface +:: +PlanningSceneInterface +psi +; +psi +. +applyCollisionObject +( +object +); +} +``` + +Language: unknown +File: task.execute() +``` +void +MTCTaskNode::doTask +() +{ +task_ += +createTask +(); +try +{ +task_ +. +init +(); +} +catch +( +mtc +:: +InitStageException +& +e +) +{ +RCLCPP_ERROR_STREAM +( +LOGGER +, +e +); +return +; +} +if +( +! +task_ +. +plan +( +5 +)) +{ +RCLCPP_ERROR_STREAM +( +LOGGER +, +"Task planning failed" +); +return +; +} +task_ +. +introspection +(). +publishSolution +( +* +task_ +. +solutions +(). +front +()); +auto +result += +task_ +. +execute +( +* +task_ +. +solutions +(). +front +()); +if +( +result +. +val +!= +moveit_msgs +:: +msg +:: +MoveItErrorCodes +:: +SUCCESS +) +{ +RCLCPP_ERROR_STREAM +( +LOGGER +, +"Task execution failed" +); +return +; +} +return +; +} +``` + +Language: unknown +File: task.setProperty(property_name,value) +``` +mtc +:: +Task +MTCTaskNode::createTask +() +{ +moveit +:: +task_constructor +:: +Task +task +; +task +. +stages +() +-> +setName +( +"demo task" +); +task +. +loadRobotModel +( +node_ +); +const +auto +& +arm_group_name += +"panda_arm" +; +const +auto +& +hand_group_name += +"hand" +; +const +auto +& +hand_frame += +"panda_hand" +; +// Set task properties +task +. +setProperty +( +"group" +, +arm_group_name +); +task +. +setProperty +( +"eef" +, +hand_group_name +); +task +. +setProperty +( +"ik_frame" +, +hand_frame +); +``` + +Language: unknown +File: current_state_ptr +``` +mtc +:: +Stage +* +current_state_ptr += +nullptr +; +// Forward current_state on to grasp pose generator +auto +stage_state_current += +std +:: +make_unique +< +mtc +:: +stages +:: +CurrentState +> +( +"current" +); +current_state_ptr += +stage_state_current +. +get +(); +task +. +add +( +std +:: +move +( +stage_state_current +)); +``` + +Language: unknown +File: current_state_ptr +``` +auto +sampling_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +PipelinePlanner +> +( +node_ +); +``` + +Language: unknown +File: current_state_ptr +``` +auto +interpolation_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +JointInterpolationPlanner +> +(); +``` + +Language: unknown +File: current_state_ptr +``` +auto +cartesian_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +CartesianPath +> +(); +``` + +Language: unknown +File: current_state_ptr +``` +auto +cartesian_planner += +std +:: +make_shared +< +mtc +:: +solvers +:: +CartesianPath +> +(); +cartesian_planner +-> +setMaxVelocityScalingFactor +( +1.0 +); +cartesian_planner +-> +setMaxAccelerationScalingFactor +( +1.0 +); +cartesian_planner +-> +setStepSize +( +.01 +); +``` + +Language: unknown +File: createTask() +``` +auto +stage_open_hand += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveTo +> +( +"open hand" +, +interpolation_planner +); +stage_open_hand +-> +setGroup +( +hand_group_name +); +stage_open_hand +-> +setGoal +( +"open" +); +task +. +add +( +std +:: +move +( +stage_open_hand +)); +return +task +; +} +``` + +Language: unknown +File: main +``` +int +main +( +int +argc +, +char +** +argv +) +{ +rclcpp +:: +init +( +argc +, +argv +); +rclcpp +:: +NodeOptions +options +; +options +. +automatically_declare_parameters_from_overrides +( +true +); +auto +mtc_task_node += +std +:: +make_shared +< +MTCTaskNode +> +( +options +); +rclcpp +:: +executors +:: +MultiThreadedExecutor +executor +; +auto +spin_thread += +std +:: +make_unique +< +std +:: +thread +> +([ +& +executor +, +& +mtc_task_node +]() +{ +executor +. +add_node +( +mtc_task_node +-> +getNodeBaseInterface +()); +executor +. +spin +(); +executor +. +remove_node +( +mtc_task_node +-> +getNodeBaseInterface +()); +}); +mtc_task_node +-> +setupPlanningScene +(); +mtc_task_node +-> +doTask +(); +spin_thread +-> +join +(); +rclcpp +:: +shutdown +(); +return +0 +; +} +``` + +Language: unknown +File: executable +``` +from +launch +import +LaunchDescription +from +launch_ros.actions +import +Node +from +moveit_configs_utils +import +MoveItConfigsBuilder +def +generate_launch_description +(): +moveit_config += +MoveItConfigsBuilder +( +"moveit_resources_panda" +) +. +to_dict +() +# MTC Demo node +pick_place_demo += +Node +( +package += +"mtc_tutorial" +, +executable += +"mtc_node" +, +output += +"screen" +, +parameters += +[ +moveit_config +, +], +) +return +LaunchDescription +([ +pick_place_demo +]) +``` + +Language: unknown +File: CMakeLists.txt +``` +install(DIRECTORY launch + DESTINATION share/${PROJECT_NAME} + ) + +``` + +Language: unknown +File: CMakeLists.txt +``` +cd +~/ +ws_moveit +colcon +build +-- +mixin +release +source +~/ +ws_moveit +/ +install +/ +setup +. +bash +``` + +Language: unknown +File: CMakeLists.txt +``` +ros2 +launch +moveit2_tutorials +mtc_demo +. +launch +. +py +``` + +Language: unknown +File: mtc_tutorial +``` +ros2 +launch +mtc_tutorial +pick_place_demo +. +launch +. +py +``` + +Language: unknown +File: mtc_tutorial +``` +ros2 +launch +moveit2_tutorials +mtc_demo_minimal +. +launch +. +py +``` + +Language: unknown +File: mtc_node.cpp +``` +auto +stage_open_hand += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveTo +> +( +"open hand" +, +interpolation_planner +); +stage_open_hand +-> +setGroup +( +hand_group_name +); +stage_open_hand +-> +setGoal +( +"open" +); +task +. +add +( +std +:: +move +( +stage_open_hand +)); +// Add the next lines of codes to define more stages here +``` + +Language: unknown +File: GroupPlannerVector +``` +auto +stage_move_to_pick += +std +:: +make_unique +< +mtc +:: +stages +:: +Connect +> +( +"move to pick" +, +mtc +:: +stages +:: +Connect +:: +GroupPlannerVector +{ +{ +arm_group_name +, +sampling_planner +} +}); +stage_move_to_pick +-> +setTimeout +( +5.0 +); +stage_move_to_pick +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +); +task +. +add +( +std +:: +move +( +stage_move_to_pick +)); +``` + +Language: unknown +File: nullptr +``` +mtc +:: +Stage +* +attach_object_stage += +nullptr +; +// Forward attach_object_stage to place pose generator +``` + +Language: unknown +File: configureInitFrom() +``` +{ +auto +grasp += +std +:: +make_unique +< +mtc +:: +SerialContainer +> +( +"pick object" +); +task +. +properties +(). +exposeTo +( +grasp +-> +properties +(), +{ +"eef" +, +"group" +, +"ik_frame" +}); +grasp +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"eef" +, +"group" +, +"ik_frame" +}); +``` + +Language: unknown +File: Vector3Stamped +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveRelative +> +( +"approach object" +, +cartesian_planner +); +stage +-> +properties +(). +set +( +"marker_ns" +, +"approach_object" +); +stage +-> +properties +(). +set +( +"link" +, +hand_frame +); +stage +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"group" +}); +stage +-> +setMinMaxDistance +( +0.1 +, +0.15 +); +// Set hand forward direction +geometry_msgs +:: +msg +:: +Vector3Stamped +vec +; +vec +. +header +. +frame_id += +hand_frame +; +vec +. +vector +. +z += +1.0 +; +stage +-> +setDirection +( +vec +); +grasp +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: current_state_ptr +``` +{ +// Sample grasp pose +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +GenerateGraspPose +> +( +"generate grasp pose" +); +stage +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +); +stage +-> +properties +(). +set +( +"marker_ns" +, +"grasp_pose" +); +stage +-> +setPreGraspPose +( +"open" +); +stage +-> +setObject +( +"object" +); +stage +-> +setAngleDelta +( +M_PI +/ +12 +); +stage +-> +setMonitoredStage +( +current_state_ptr +); +// Hook into current state +``` + +Language: unknown +File: geometry_msgs +``` +Eigen +:: +Isometry3d +grasp_frame_transform +; +Eigen +:: +Quaterniond +q += +Eigen +:: +AngleAxisd +( +M_PI +/ +2 +, +Eigen +:: +Vector3d +:: +UnitX +()) +* +Eigen +:: +AngleAxisd +( +M_PI +/ +2 +, +Eigen +:: +Vector3d +:: +UnitY +()) +* +Eigen +:: +AngleAxisd +( +M_PI +/ +2 +, +Eigen +:: +Vector3d +:: +UnitZ +()); +grasp_frame_transform +. +linear +() += +q +. +matrix +(); +grasp_frame_transform +. +translation +(). +z +() += +0.1 +; +``` + +Language: unknown +File: ComputeIK +``` +// Compute IK +auto +wrapper += +std +:: +make_unique +< +mtc +:: +stages +:: +ComputeIK +> +( +"grasp pose IK" +, +std +:: +move +( +stage +)); +wrapper +-> +setMaxIKSolutions +( +8 +); +wrapper +-> +setMinSolutionDistance +( +1.0 +); +wrapper +-> +setIKFrame +( +grasp_frame_transform +, +hand_frame +); +wrapper +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"eef" +, +"group" +}); +wrapper +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +INTERFACE +, +{ +"target_pose" +}); +grasp +-> +insert +( +std +:: +move +( +wrapper +)); +} +``` + +Language: unknown +File: getLinkModelNamesWithCollisionGeometry +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +ModifyPlanningScene +> +( +"allow collision (hand,object)" +); +stage +-> +allowCollisions +( +"object" +, +task +. +getRobotModel +() +-> +getJointModelGroup +( +hand_group_name +) +-> +getLinkModelNamesWithCollisionGeometry +(), +true +); +grasp +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: close +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveTo +> +( +"close hand" +, +interpolation_planner +); +stage +-> +setGroup +( +hand_group_name +); +stage +-> +setGoal +( +"close" +); +grasp +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: current_state_ptr +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +ModifyPlanningScene +> +( +"attach object" +); +stage +-> +attachObject +( +"object" +, +hand_frame +); +attach_object_stage += +stage +. +get +(); +grasp +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: approach_object +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveRelative +> +( +"lift object" +, +cartesian_planner +); +stage +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"group" +}); +stage +-> +setMinMaxDistance +( +0.1 +, +0.3 +); +stage +-> +setIKFrame +( +hand_frame +); +stage +-> +properties +(). +set +( +"marker_ns" +, +"lift_object" +); +// Set upward direction +geometry_msgs +:: +msg +:: +Vector3Stamped +vec +; +vec +. +header +. +frame_id += +"world" +; +vec +. +vector +. +z += +1.0 +; +stage +-> +setDirection +( +vec +); +grasp +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: approach_object +``` +task +. +add +( +std +:: +move +( +grasp +)); +} +``` + +Language: unknown +File: approach_object +``` +ros2 +launch +mtc_tutorial +pick_place_demo +. +launch +. +py +``` + +Language: unknown +File: Connect +``` +{ +auto +stage_move_to_place += +std +:: +make_unique +< +mtc +:: +stages +:: +Connect +> +( +"move to place" +, +mtc +:: +stages +:: +Connect +:: +GroupPlannerVector +{ +{ +arm_group_name +, +sampling_planner +}, +{ +hand_group_name +, +interpolation_planner +} +}); +stage_move_to_place +-> +setTimeout +( +5.0 +); +stage_move_to_place +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +); +task +. +add +( +std +:: +move +( +stage_move_to_place +)); +} +``` + +Language: unknown +File: Connect +``` +{ +auto +place += +std +:: +make_unique +< +mtc +:: +SerialContainer +> +( +"place object" +); +task +. +properties +(). +exposeTo +( +place +-> +properties +(), +{ +"eef" +, +"group" +, +"ik_frame" +}); +place +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"eef" +, +"group" +, +"ik_frame" +}); +``` + +Language: unknown +File: GeneratePlacePose +``` +{ +// Sample place pose +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +GeneratePlacePose +> +( +"generate place pose" +); +stage +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +); +stage +-> +properties +(). +set +( +"marker_ns" +, +"place_pose" +); +stage +-> +setObject +( +"object" +); +geometry_msgs +:: +msg +:: +PoseStamped +target_pose_msg +; +target_pose_msg +. +header +. +frame_id += +"object" +; +target_pose_msg +. +pose +. +position +. +y += +0.5 +; +target_pose_msg +. +pose +. +orientation +. +w += +1.0 +; +stage +-> +setPose +( +target_pose_msg +); +stage +-> +setMonitoredStage +( +attach_object_stage +); +// Hook into attach_object_stage +// Compute IK +auto +wrapper += +std +:: +make_unique +< +mtc +:: +stages +:: +ComputeIK +> +( +"place pose IK" +, +std +:: +move +( +stage +)); +wrapper +-> +setMaxIKSolutions +( +2 +); +wrapper +-> +setMinSolutionDistance +( +1.0 +); +wrapper +-> +setIKFrame +( +"object" +); +wrapper +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"eef" +, +"group" +}); +wrapper +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +INTERFACE +, +{ +"target_pose" +}); +place +-> +insert +( +std +:: +move +( +wrapper +)); +} +``` + +Language: unknown +File: MoveTo +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveTo +> +( +"open hand" +, +interpolation_planner +); +stage +-> +setGroup +( +hand_group_name +); +stage +-> +setGoal +( +"open" +); +place +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: true +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +ModifyPlanningScene +> +( +"forbid collision (hand,object)" +); +stage +-> +allowCollisions +( +"object" +, +task +. +getRobotModel +() +-> +getJointModelGroup +( +hand_group_name +) +-> +getLinkModelNamesWithCollisionGeometry +(), +false +); +place +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: detachObject +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +ModifyPlanningScene +> +( +"detach object" +); +stage +-> +detachObject +( +"object" +, +hand_frame +); +place +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: liftobject +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveRelative +> +( +"retreat" +, +cartesian_planner +); +stage +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"group" +}); +stage +-> +setMinMaxDistance +( +0.1 +, +0.3 +); +stage +-> +setIKFrame +( +hand_frame +); +stage +-> +properties +(). +set +( +"marker_ns" +, +"retreat" +); +// Set retreat direction +geometry_msgs +:: +msg +:: +Vector3Stamped +vec +; +vec +. +header +. +frame_id += +"world" +; +vec +. +vector +. +x += +-0.5 +; +stage +-> +setDirection +( +vec +); +place +-> +insert +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: liftobject +``` +task +. +add +( +std +:: +move +( +place +)); +} +``` + +Language: unknown +File: ready +``` +{ +auto +stage += +std +:: +make_unique +< +mtc +:: +stages +:: +MoveTo +> +( +"return home" +, +interpolation_planner +); +stage +-> +properties +(). +configureInitFrom +( +mtc +:: +Stage +:: +PARENT +, +{ +"group" +}); +stage +-> +setGoal +( +"ready" +); +task +. +add +( +std +:: +move +( +stage +)); +} +``` + +Language: unknown +File: ready +``` +// Stages all added to the task above this line +return +task +; +} +``` + +Language: unknown +File: ready +``` +ros2 +launch +mtc_tutorial +pick_place_demo +. +launch +. +py +``` + +Language: unknown +File: ready +``` +ros2 +launch +moveit2_tutorials +mtc_demo +. +launch +. +py +``` + +Language: unknown +File: ready +``` +ros2 +launch +moveit2_tutorials +pick_place_demo +. +launch +. +py +``` + +Language: unknown +File: ready +``` +[ +demo_node-1 +] +1 +- +← +1 +→ +- +0 +/ +initial_state + +[ +demo_node-1 +] +- +0 +→ +0 +→ +- +0 +/ +move_to_home + +``` + +Language: unknown +File: 0 +``` +uint32_t +const +unique_stage_id += +task_ +. +stages +() +-> +findChild +( +stage_name +) +-> +introspectionId +(); +``` diff --git "a/exported_docs/moveit2/Planning Around Objects\357\203\201.txt" "b/exported_docs/moveit2/Planning Around Objects\357\203\201.txt" new file mode 100644 index 0000000..77718f8 --- /dev/null +++ "b/exported_docs/moveit2/Planning Around Objects\357\203\201.txt" @@ -0,0 +1,325 @@ +Title: Planning Around Objects +URL: https://moveit.picknik.ai/main/doc/tutorials/planning_around_objects/planning_around_objects.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Prerequisites +If you haven’t already done so, make sure you’ve completed the steps inVisualizing in RViz. +This project assumes you are starting with thehello_moveitproject, where the previous tutorial left off. If you just want to run the tutorial, you can follow theDocker Guideto start a container with the completed tutorial. + +## Steps + + +## 1 Add include for Planning Scene Interface +At the top of your source file, add this to the list of includes: + +## 2 Change the Target Pose +First, update the target pose with the following change to make the robot plan to a different location: + +## 3 Create a Collision Object +In the next block of code, we create a collision object. +The first thing to notice is that it is being placed in the coordinate frame of the robot. +If we had a perception system that reported the location of obstacles in our scene, then this is the sort of message it would build. +Because this is just an example, we are creating it manually. +One thing to notice at the end of this block of code is that we set the operation on this message toADD. +This results in the object getting added to the collision scene. +Place this code block between setting the target pose from the previous step and creating a plan. + +## 4 Add the Object to the Planning Scene +Finally, we need to add this object to the collision scene. +To do this, we use an object called thePlanningSceneInterfacethat uses ROS interfaces to communicate changes to the planning scene toMoveGroup. +This code block should directly follow the code block that creates the collision object. + +## 5 Run the Program and Observe the Change +Just as we did in the last tutorial, start RViz using thedemo.launch.pyscript and run our program. If you’re using one of the Docker tutorial containers, you can specify a different RViz configuration that already has the RvizVisualToolsGui panel added using: + +## Summary + + +## Further Reading + + +## Next Step +In the next tutorialPick and Place with MoveIt Task Constructor, you will be introduced to a higher layer tool designed to solve harder motion plans. +In this next tutorial, you will create a program to pick and place an object. + +Code Examples: + +Language: unknown +File: hello_moveit +``` +#include + +``` + +Language: unknown +File: hello_moveit +``` +// Set a target Pose with updated values !!! +auto +const +target_pose += +[] +{ +geometry_msgs +:: +msg +:: +Pose +msg +; +msg +. +orientation +. +y += +0.8 +; +msg +. +orientation +. +w += +0.6 +; +msg +. +position +. +x += +0.1 +; +msg +. +position +. +y += +0.4 +; +msg +. +position +. +z += +0.4 +; +return +msg +; +}(); +move_group_interface +. +setPoseTarget +( +target_pose +); +``` + +Language: unknown +File: ADD +``` +// Create collision object for the robot to avoid +auto +const +collision_object += +[ +frame_id += +move_group_interface +. +getPlanningFrame +()] +{ +moveit_msgs +:: +msg +:: +CollisionObject +collision_object +; +collision_object +. +header +. +frame_id += +frame_id +; +collision_object +. +id += +"box1" +; +shape_msgs +:: +msg +:: +SolidPrimitive +primitive +; +// Define the size of the box in meters +primitive +. +type += +primitive +. +BOX +; +primitive +. +dimensions +. +resize +( +3 +); +primitive +. +dimensions +[ +primitive +. +BOX_X +] += +0.5 +; +primitive +. +dimensions +[ +primitive +. +BOX_Y +] += +0.1 +; +primitive +. +dimensions +[ +primitive +. +BOX_Z +] += +0.5 +; +// Define the pose of the box (relative to the frame_id) +geometry_msgs +:: +msg +:: +Pose +box_pose +; +box_pose +. +orientation +. +w += +1.0 +; +// We can leave out the x, y, and z components of the quaternion since they are initialized to 0 +box_pose +. +position +. +x += +0.2 +; +box_pose +. +position +. +y += +0.2 +; +box_pose +. +position +. +z += +0.25 +; +collision_object +. +primitives +. +push_back +( +primitive +); +collision_object +. +primitive_poses +. +push_back +( +box_pose +); +collision_object +. +operation += +collision_object +. +ADD +; +return +collision_object +; +}(); +``` + +Language: unknown +File: MoveGroup +``` +// Add the collision object to the scene +moveit +:: +planning_interface +:: +PlanningSceneInterface +planning_scene_interface +; +planning_scene_interface +. +applyCollisionObject +( +collision_object +); +``` + +Language: unknown +File: demo.launch.py +``` +ros2 +launch +moveit2_tutorials +demo +. +launch +. +py +rviz_config +:= +kinova_hello_moveit +. +rviz +``` diff --git "a/exported_docs/moveit2/Planning Scene Monitor\357\203\201.txt" "b/exported_docs/moveit2/Planning Scene Monitor\357\203\201.txt" new file mode 100644 index 0000000..33d0d1c --- /dev/null +++ "b/exported_docs/moveit2/Planning Scene Monitor\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: Planning Scene Monitor +URL: https://moveit.picknik.ai/main/doc/concepts/planning_scene_monitor.html +Section: index.html +-------------------------------------------------------------------------------- + + +## World Geometry Monitor +The world geometry monitor builds world geometry using information from the sensors on the robot such as LIDARs or depth cameras and from user input. +It uses theoccupancymapmonitordescribed below to build a 3D representation of the environment around the robot and augments that with information on theplanning_scenetopic for adding object information. + +## 3D Perception +3D perception in MoveIt is handled by theoccupancymapmonitor. +The occupancy map monitor uses a plugin architecture to handle different kinds of sensor input as shown in the Figure above. +In particular, MoveIt has inbuilt support for handling two kinds of inputs: +Note that you can add your own types of updaters as a plugin to the occupancy map monitor. + +## Octomap +The Occupancy map monitor uses anOctomapto maintain the occupancy map of the environment. +The Octomap can actually encode probabilistic information about individual cells although this information is not currently used in MoveIt. +The Octomap can directly be passed into FCL, the collision checking library that MoveIt uses. + +## Depth Image Occupancy Map Updater +The depth image occupancy map updater includes its ownself-filter, i.e. it will remove visible parts of the robot from the depth map. +It uses current information about the robot (the robot state) to carry out this operation. diff --git "a/exported_docs/moveit2/Python API Documentation\357\203\201.txt" "b/exported_docs/moveit2/Python API Documentation\357\203\201.txt" new file mode 100644 index 0000000..ad39ed9 --- /dev/null +++ "b/exported_docs/moveit2/Python API Documentation\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Python API Documentation +URL: https://moveit.picknik.ai/main/doc/api/python_api/api.html +Section: index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Themove_groupnode\357\203\201.txt" "b/exported_docs/moveit2/Themove_groupnode\357\203\201.txt" new file mode 100644 index 0000000..e953e5a --- /dev/null +++ "b/exported_docs/moveit2/Themove_groupnode\357\203\201.txt" @@ -0,0 +1,42 @@ +Title: Themove_groupnode +URL: https://moveit.picknik.ai/main/doc/concepts/move_group.html +Section: index.html +-------------------------------------------------------------------------------- + + +## User Interface +The users can access the actions and services provided bymove_groupin two ways: + +## Configuration +move_groupis a ROS node. +It uses the ROS param server to get three kinds of information: + +## Robot Interface +move_grouptalks to the robot through ROS topics and actions. +It communicates with the robot to get current state information (positions of the joints, etc.), to get point clouds and other sensor data from the robot sensors and to talk to the controllers on the robot. + +## Joint State Information +move_grouplistens on the/joint_statestopic for determining the current state information - i.e. determining where each joint of the robot is.move_groupis capable of listening to multiple publishers on this topic even if they are publishing only partial information about the robot state (e.g. separate publishers may be used for the arm and mobile base of a robot). +Note thatmove_groupwill not set up its own joint state publisher - this is something that has to be implemented on each robot. + +## Transform Information +move_groupmonitors transform information using the ROS TF library. +This allows the node to get global information about the pose of the robot (among other things). +For instance, the ROS navigation stack will publish the transform between the map frame and base frame of the robot to TF.move_groupcan use TF to figure out this transform for internal use. Note thatmove_grouponly listens to TF. +To publish TF information from your robot, you will need to have arobot_state_publishernode running on your robot. + +## Controller Interface +move_grouptalks to the controllers on the robot using the FollowJointTrajectoryAction interface. +This is a ROS action interface. +A server on the robot needs to service this action - this server is not provided bymove_groupitself.move_groupwill only instantiate a client to talk to this controller action server on your robot. + +## Planning Scene +move_groupuses the Planning Scene Monitor to maintain aplanning scene, which is a representation of the world and the current state of the robot. +The robot state can include any objects attached to (carried by) the robot which are considered to be rigidly attached to the robot. +More details on the architecture for maintaining and updating theplanning sceneare outlined in the Planning Scene section below. + +## Extensible Capabilities +move_groupis structured to be easily extensible. +Individual capabilities like pick and place, kinematics, motion planning are actually implemented as separate plugins with a common base class. +The plugins are configurable using ROS through a set of ROS yaml parameters and through the use of the ROS pluginlib library. +Most users will not have to configure move_group plugins since they come automatically configured in the launch files generated by the MoveIt Setup Assistant. diff --git "a/exported_docs/moveit2/Trajectory Processing\357\203\201.txt" "b/exported_docs/moveit2/Trajectory Processing\357\203\201.txt" new file mode 100644 index 0000000..8fdc301 --- /dev/null +++ "b/exported_docs/moveit2/Trajectory Processing\357\203\201.txt" @@ -0,0 +1,14 @@ +Title: Trajectory Processing +URL: https://moveit.picknik.ai/main/doc/concepts/trajectory_processing.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Time parameterization +Motion planners typically only generate “paths”, i.e. there is no timing information associated with the paths. +MoveIt includes severaltrajectory processingalgorithms that can work on these paths and generate trajectories that are properly time-parameterized accounting for the maximum velocity and acceleration limits imposed on individual joints. +These limits are read from a specialjoint_limits.yamlconfiguration file that is specified for each robot. +The configuration file is optional and it overrides any velocity or acceleration limits from the URDF. +The recommended algorithm as of January 2023 isTimeOptimalTrajectoryGeneration(TOTG). +A caveat for this algorithm is that the robot must start and end at rest. +By default, the TOTG timestep is 0.1 seconds. diff --git "a/exported_docs/moveit2/Tutorials\357\203\201.txt" "b/exported_docs/moveit2/Tutorials\357\203\201.txt" new file mode 100644 index 0000000..34dfd43 --- /dev/null +++ "b/exported_docs/moveit2/Tutorials\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Tutorials +URL: https://moveit.picknik.ai/main/doc/tutorials/tutorials.html +Section: doc/tutorials/tutorials.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/moveit2/Visualizing In RViz\357\203\201.txt" "b/exported_docs/moveit2/Visualizing In RViz\357\203\201.txt" new file mode 100644 index 0000000..508c54d --- /dev/null +++ "b/exported_docs/moveit2/Visualizing In RViz\357\203\201.txt" @@ -0,0 +1,621 @@ +Title: Visualizing In RViz +URL: https://moveit.picknik.ai/main/doc/tutorials/visualizing_in_rviz/visualizing_in_rviz.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Prerequisites +If you haven’t already done so, make sure you’ve completed the steps inYour First Project. +This project assumes you are starting with thehello_moveitproject, where the previous tutorial left off. + +## Steps + + +## 1 Add the dependency moveit_visual_tools +Add this line to yourpackage.xmlin thehello_moveitproject after the otherstatements: +Then in yourCMakeLists.txtadd this line to the section offind_packagestatements: +Further down in the file extend theament_target_dependenciesmacro call to include the new dependency like this: +To verify that you added the dependency correctly, add the required include to your source filehello_moveit.cpp: +To test that this all worked, open a terminal in the workspace directory (remembering to source your ROS install in opt) and then build with colcon: + +## 2 Create a ROS executor and spin the node on a thread +Before we can initialize MoveItVisualTools, we need to have a executor spinning on our ROS node. +This is necessary because of how MoveItVisualTools interacts with ROS services and topics. First, add the threading library to your includes at the top. +By creating and naming loggers, we are able to keep our program logs organized. +Next, add your executor before creating the MoveIt MoveGroup Interface. +Finally, make sure to join the thread before exiting. +After making these changes, rebuild your workspace to make sure you don’t have any syntax errors. + +## 3 Create and Initialize MoveItVisualTools +Next, we will construct and initialize MoveItVisualTools after the construction of MoveGroupInterface. +We pass the following into the constructor: the ROS node, the base link of the robot, the marker topic to use (more on this later), and the robot model (which we get from the move_group_interface). +Next, we make a call to delete all the markers. This clears any rendered state out of RViz that we have left over from previous runs. +Lastly, we load remote control. +Remote control is a really simple plugin that lets us have a button in RViz to interact with our program. + +## 4 Write closures for visualizations +After we’ve constructed and initialized, we now create some closures (function objects that have access to variables in our current scope) that we can use later in our program to help render visualizations in RViz. +Each of the three closures capturemoveit_visual_toolsby reference and the last one captures a pointer to the joint model group object we are planning with. +Each of these call a function onmoveit_visual_toolsthat changes something in RViz. +You might be asking yourself why we would create lambdas like this, and the reason is simply to make the code that comes later easier to read and understand. +As your write software, it is often helpful to break up your functionality into named functions which can be easily reused and tested on their own. +You will see in the next section how we use these functions we created. + +## 5 Visualize the steps of your program +Now we’ll augment the code in the middle of your program. +Update your code for planning and executing to include these new features: +One thing you’ll quickly notice is that we have to call a method calledtriggeronmoveit_visual_toolsafter each call to change something rendered in RViz. +The reason for this is that messages sent to RViz are batched up and sent when you calltriggerto reduce bandwidth of the marker topics. +Lastly, build your project again to make sure all the code additions are correct. + +## 6 Enable visualizations in RViz +Open a new terminal, source the workspace, and then start the demo launch file that opens RViz. +Uncheck “MotionPlanning” in the “Displays” tab to hide it. +We aren’t going to be using the “MotionPlanning” plugin for this next part. +To add the buttons to interact with the prompts we added to our program open the dialog with the “Panels/Add New Panel” menu: +Then selectRvizVisualToolsGuiand click OK. +This will create a new panel on the bottom left with aNextbutton we’ll use later. +Finally, we need to add aMarkerArrayto render the visualizations we’ve added. +Click on the “Add” Button in the “Displays” panel. +SelectMarkerArrayand clickOK. +Scroll to the bottom of the items in the Displays panel and edit the topic that the new Marker Array is using to/rviz_visual_tools. +You are now ready to run your new program with visualizations. + +## 7 Run the Program +In a new terminal, go to the workspace, source the workspace, and runhello_moveit: +You’ll notice that your program has stopped with a log that looks like this: +Click theNextbutton in RViz and see your application advance. +You’ll see after you clicked the next button, your application planned, added a title above the robot, and drew a line representing the tool path. +To continue, pressNextagain to see your robot execute the plan. + +## Summary +You extended the program you wrote with MoveIt to interact with the Gui in RViz, allowing you to step through your program with a button, render some text above the robot, and display the tool path that you planned. + +## Further Reading + + +## Next Step +In the next tutorialPlanning Around Objects, you will expand on the program you built here to add to the collision environment and see the robot plan with these changes. + +Code Examples: + +Language: unknown +File: +``` + +moveit_visual_tools + +``` + +Language: unknown +File: find_package +``` +find_package +( +moveit_visual_tools +REQUIRED +) +``` + +Language: unknown +File: ament_target_dependencies +``` +ament_target_dependencies +( +hello_moveit +"moveit_ros_planning_interface" +"moveit_visual_tools" +"rclcpp" +) +``` + +Language: unknown +File: hello_moveit.cpp +``` +#include + +``` + +Language: unknown +File: hello_moveit.cpp +``` +cd +~/ws_moveit +colcon +build +--mixin +debug + +``` + +Language: unknown +File: hello_moveit.cpp +``` +#include + + // <---- add this to the set of includes at the top +``` + +Language: unknown +File: hello_moveit.cpp +``` +// Create a ROS logger +auto +const +logger += +rclcpp +:: +get_logger +( +"hello_moveit" +); +``` + +Language: unknown +File: hello_moveit.cpp +``` +// Spin up a SingleThreadedExecutor for MoveItVisualTools to interact with ROS +rclcpp +:: +executors +:: +SingleThreadedExecutor +executor +; +executor +. +add_node +( +node +); +auto +spinner += +std +:: +thread +([ +& +executor +]() +{ +executor +. +spin +(); +}); +// Create the MoveIt MoveGroup Interface +... +``` + +Language: unknown +File: hello_moveit.cpp +``` +// Shutdown ROS +rclcpp +:: +shutdown +(); +// <--- This will cause the spin function in the thread to return +spinner +. +join +(); +// <--- Join the thread before exiting +return +0 +; +``` + +Language: unknown +File: hello_moveit.cpp +``` +// Create the MoveIt MoveGroup Interface +using +moveit +:: +planning_interface +:: +MoveGroupInterface +; +auto +move_group_interface += +MoveGroupInterface +( +node +, +"manipulator" +); +// Construct and initialize MoveItVisualTools +auto +moveit_visual_tools += +moveit_visual_tools +:: +MoveItVisualTools +{ +node +, +"base_link" +, +rviz_visual_tools +:: +RVIZ_MARKER_TOPIC +, +move_group_interface +. +getRobotModel +()}; +moveit_visual_tools +. +deleteAllMarkers +(); +moveit_visual_tools +. +loadRemoteControl +(); +``` + +Language: unknown +File: hello_moveit.cpp +``` +// Create closures for visualization +auto +const +draw_title += +[ +& +moveit_visual_tools +]( +auto +text +) +{ +auto +const +text_pose += +[] +{ +auto +msg += +Eigen +:: +Isometry3d +:: +Identity +(); +msg +. +translation +(). +z +() += +1.0 +; +// Place text 1m above the base link +return +msg +; +}(); +moveit_visual_tools +. +publishText +( +text_pose +, +text +, +rviz_visual_tools +:: +WHITE +, +rviz_visual_tools +:: +XLARGE +); +}; +auto +const +prompt += +[ +& +moveit_visual_tools +]( +auto +text +) +{ +moveit_visual_tools +. +prompt +( +text +); +}; +auto +const +draw_trajectory_tool_path += +[ +& +moveit_visual_tools +, +jmg += +move_group_interface +. +getRobotModel +() +-> +getJointModelGroup +( +"manipulator" +)]( +auto +const +trajectory +) +{ +moveit_visual_tools +. +publishTrajectoryLine +( +trajectory +, +jmg +); +}; +``` + +Language: unknown +File: next +``` +// Set a target Pose +auto +const +target_pose += +[] +{ +geometry_msgs +:: +msg +:: +Pose +msg +; +msg +. +orientation +. +w += +1.0 +; +msg +. +position +. +x += +0.28 +; +msg +. +position +. +y += +-0.2 +; +msg +. +position +. +z += +0.5 +; +return +msg +; +}(); +move_group_interface +. +setPoseTarget +( +target_pose +); +// Create a plan to that target pose +prompt +( +"Press 'Next' in the RvizVisualToolsGui window to plan" +); +draw_title +( +"Planning" +); +moveit_visual_tools +. +trigger +(); +auto +const +[ +success +, +plan +] += +[ +& +move_group_interface +] +{ +moveit +:: +planning_interface +:: +MoveGroupInterface +:: +Plan +msg +; +auto +const +ok += +static_cast +< +bool +> +( +move_group_interface +. +plan +( +msg +)); +return +std +:: +make_pair +( +ok +, +msg +); +}(); +// Execute the plan +if +( +success +) +{ +draw_trajectory_tool_path +( +plan +. +trajectory +); +moveit_visual_tools +. +trigger +(); +prompt +( +"Press 'Next' in the RvizVisualToolsGui window to execute" +); +draw_title +( +"Executing" +); +moveit_visual_tools +. +trigger +(); +move_group_interface +. +execute +( +plan +); +} +else +{ +draw_title +( +"Planning Failed!" +); +moveit_visual_tools +. +trigger +(); +RCLCPP_ERROR +( +logger +, +"Planning failed!" +); +} +``` + +Language: unknown +File: trigger +``` +cd +~/ws_moveit + +source +/opt/ros/rolling/setup.bash +colcon +build +--mixin +debug + +``` + +Language: unknown +File: trigger +``` +cd +~/ws_moveit + +source +install/setup.bash +ros2 +launch +moveit2_tutorials +demo.launch.py + +``` + +Language: unknown +File: hello_moveit +``` +cd +~/ws_moveit + +source +install/setup.bash +ros2 +run +hello_moveit +hello_moveit + +``` + +Language: unknown +File: hello_moveit +``` +[ +INFO +] +[ +1652822889.492940200 +] +[ +hello_moveit +. +remote_control +]: +Waiting +to +continue +: +Press +'Next' +in +the +RvizVisualToolsGui +window +to +plan +``` diff --git "a/exported_docs/moveit2/Your First C++ MoveIt Project\357\203\201.txt" "b/exported_docs/moveit2/Your First C++ MoveIt Project\357\203\201.txt" new file mode 100644 index 0000000..c997985 --- /dev/null +++ "b/exported_docs/moveit2/Your First C++ MoveIt Project\357\203\201.txt" @@ -0,0 +1,631 @@ +Title: Your First C++ MoveIt Project +URL: https://moveit.picknik.ai/main/doc/tutorials/your_first_project/your_first_project.html +Section: index.html +-------------------------------------------------------------------------------- + + +## Prerequisites +If you haven’t already done so, make sure you’ve completed the steps inGetting Started. +This tutorial assumes you understand the basics of ROS 2. +To prepare yourself for this please complete theOfficial ROS 2 Tutorialsup until “Writing a simple publisher and Subscriber (C++)”. + +## Steps + + +## 1 Create a package +Open a terminal andsource your ROS 2 installationso thatros2commands will work. +Navigate to yourws_moveitdirectory you created in theGetting Started Tutorial. +Change directory into thesrcdirectory, as that is where we put our source code. +Create a new package with the ROS 2 command line tools: +The output of this will show that it created some files in a new directory. +Note that we addedmoveit_ros_planning_interfaceandrclcppas dependencies. +This will create the necessary changes in thepackage.xmlandCMakeLists.txtfiles so that we can depend on these two packages. +Open the new source file created for you atws_moveit/src/hello_moveit/src/hello_moveit.cppin your favorite editor. + +## 2 Create a ROS Node and Executor +This first block of code is a bit of boilerplate but you should be used to seeing this from the ROS 2 tutorials. + +## 2.1 Build and Run +We will build and run the program to see that everything is right before we move on. +Change the directory back to the workspace directoryws_moveitand run this command: +After this succeeds,open a new terminal, then source the workspace environment script in that new terminal so that we can run our program. +Run your program and see the output. +The program should run and exit without error. + +## 2.2 Examine the code +The headers included at the top are just some standard C++ headers and the headers for ROS and MoveIt that we will use later. +After that, we have the normal call to initialize rclcpp, and then we create our Node. +The first argument is a string that ROS will use to name a unique node. +The second is needed for MoveIt because of how we use ROS Parameters. +Next, wecreate a loggernamed “hello_moveit” to keep our log outputs organized and configurable. +Lastly, we have the code to shutdown ROS. + +## 3 Plan and Execute using MoveGroupInterface +In place of the comment that says “Next step goes here”, add this code: + +## 3.1 Build and Run +Just like before, we need to build the code before we can run it. +In the workspace directory,ws_moveit, run this command: +After this succeeds, we need to reuse the demo launch file from the previous tutorial to start RViz and the MoveGroup node. +In a separate terminal, source the workspace and then execute this: +Then in theDisplayswindow underMotionPlanning/PlanningRequest, uncheck the boxQueryGoalState. +In a third terminal, source the workspace and run your program. +This should cause the robot in RViz to move and end up in this pose: +Note that if you run the nodehello_moveitwithout launching the demo launch file first, it will wait for 10 seconds and then print this error and exit. +This is because thedemo.launch.pylaunch is starting theMoveGroupnode that provides the robot description. +WhenMoveGroupInterfaceis constructed, it looks for a node publishing a topic with the robot description. +If it fails to find that within 10 seconds, it prints this error and terminates the program. + +## 3.2 Examine the code +The first thing we do is create theMoveGroupInterface. +This object will be used to interact withmove_group, which allows us to plan and execute trajectories. +Note that this is the only mutable object that we create in this program. +Another thing to take note of is the second argument to theMoveGroupInterfaceobject we are creating here:"manipulator". +That is the group of joints as defined in the robot description that we are going to operate on with thisMoveGroupInterface. +Then, we set our target pose and plan. Note that only the target pose is set (viasetPoseTarget). +The starting pose is implicitly the position published by the joint state publisher, which could be changed using theMoveGroupInterface::setStartState*family of functions (but is not in this tutorial). +One more thing to note about this next section is the use of lambdas for constructing the message typetarget_poseand planning. +This is a pattern you’ll find in modern C++ codebases that enables writing in a more declarative style. +For more information about this pattern, there are a couple of links at the end of this tutorial. +Finally, we execute our plan if planning is successful, otherwise, we log an error: + +## Summary + + +## Further Reading + + +## Next Step +In the next tutorialVisualizing in RViz, you will expand on the program you built here to create visual markers that make it easier to understand what MoveIt is doing. + +Code Examples: + +Language: unknown +File: src +``` +ros2 +pkg +create +\ +--build-type +ament_cmake +\ +--dependencies +moveit_ros_planning_interface +rclcpp +\ +--node-name +hello_moveit +hello_moveit + +``` + +Language: unknown +File: ws_moveit/src/hello_moveit/src/hello_moveit.cpp +``` +#include + +#include + +#include + +int +main +( +int +argc +, +char +* +argv +[]) +{ +// Initialize ROS and create the Node +rclcpp +:: +init +( +argc +, +argv +); +auto +const +node += +std +:: +make_shared +< +rclcpp +:: +Node +> +( +"hello_moveit" +, +rclcpp +:: +NodeOptions +(). +automatically_declare_parameters_from_overrides +( +true +) +); +// Create a ROS logger +auto +const +logger += +rclcpp +:: +get_logger +( +"hello_moveit" +); +// Next step goes here +// Shutdown ROS +rclcpp +:: +shutdown +(); +return +0 +; +} +``` + +Language: unknown +File: ws_moveit +``` +colcon +build +--mixin +debug + +``` + +Language: unknown +File: ws_moveit +``` +cd +~/ws_moveit + +source +install/setup.bash + +``` + +Language: unknown +File: ws_moveit +``` +ros2 +run +hello_moveit +hello_moveit + +``` + +Language: unknown +File: ws_moveit +``` +auto +const +node += +std +:: +make_shared +< +rclcpp +:: +Node +> +( +"hello_moveit" +, +rclcpp +:: +NodeOptions +(). +automatically_declare_parameters_from_overrides +( +true +) +); +``` + +Language: unknown +File: ws_moveit +``` +// Create a ROS logger +auto +const +logger += +rclcpp +:: +get_logger +( +"hello_moveit" +); +``` + +Language: unknown +File: ws_moveit +``` +// Shutdown ROS +rclcpp +:: +shutdown +(); +return +0 +; +``` + +Language: unknown +File: ws_moveit +``` +// Create the MoveIt MoveGroup Interface +using +moveit +:: +planning_interface +:: +MoveGroupInterface +; +auto +move_group_interface += +MoveGroupInterface +( +node +, +"manipulator" +); +// Set a target Pose +auto +const +target_pose += +[]{ +geometry_msgs +:: +msg +:: +Pose +msg +; +msg +. +orientation +. +w += +1.0 +; +msg +. +position +. +x += +0.28 +; +msg +. +position +. +y += +-0.2 +; +msg +. +position +. +z += +0.5 +; +return +msg +; +}(); +move_group_interface +. +setPoseTarget +( +target_pose +); +// Create a plan to that target pose +auto +const +[ +success +, +plan +] += +[ +& +move_group_interface +]{ +moveit +:: +planning_interface +:: +MoveGroupInterface +:: +Plan +msg +; +auto +const +ok += +static_cast +< +bool +> +( +move_group_interface +. +plan +( +msg +)); +return +std +:: +make_pair +( +ok +, +msg +); +}(); +// Execute the plan +if +( +success +) +{ +move_group_interface +. +execute +( +plan +); +} +else +{ +RCLCPP_ERROR +( +logger +, +"Planning failed!" +); +} +``` + +Language: unknown +File: ws_moveit +``` +colcon +build +--mixin +debug + +``` + +Language: unknown +File: ws_moveit +``` +ros2 +launch +moveit2_tutorials +demo.launch.py + +``` + +Language: unknown +File: QueryGoalState +``` +ros2 +run +hello_moveit +hello_moveit + +``` + +Language: unknown +File: hello_moveit +``` +[ +ERROR +] +[ +1644181704 +.350825487 +] +[ +hello_moveit +] +: +Could +not +find +parameter +robot_description +and +did +not +receive +robot_description +via +std_msgs::msg::String +subscription +within +10 +.000000 +seconds. + +``` + +Language: unknown +File: MoveGroupInterface +``` +using +moveit +:: +planning_interface +:: +MoveGroupInterface +; +auto +move_group_interface += +MoveGroupInterface +( +node +, +"manipulator" +); +``` + +Language: unknown +File: target_pose +``` +// Set a target Pose +auto +const +target_pose += +[]{ +geometry_msgs +:: +msg +:: +Pose +msg +; +msg +. +orientation +. +w += +1.0 +; +msg +. +position +. +x += +0.28 +; +msg +. +position +. +y += +-0.2 +; +msg +. +position +. +z += +0.5 +; +return +msg +; +}(); +move_group_interface +. +setPoseTarget +( +target_pose +); +// Create a plan to that target pose +auto +const +[ +success +, +plan +] += +[ +& +move_group_interface +]{ +moveit +:: +planning_interface +:: +MoveGroupInterface +:: +Plan +msg +; +auto +const +ok += +static_cast +< +bool +> +( +move_group_interface +. +plan +( +msg +)); +return +std +:: +make_pair +( +ok +, +msg +); +}(); +``` + +Language: unknown +File: target_pose +``` +// Execute the plan +if +( +success +) +{ +move_group_interface +. +execute +( +plan +); +} +else +{ +RCLCPP_ERROR +( +logger +, +"Planning failed!" +); +} +``` diff --git "a/exported_docs/nav2/(SLAM) Navigating While Mapping\357\203\201.txt" "b/exported_docs/nav2/(SLAM) Navigating While Mapping\357\203\201.txt" new file mode 100644 index 0000000..25261ec --- /dev/null +++ "b/exported_docs/nav2/(SLAM) Navigating While Mapping\357\203\201.txt" @@ -0,0 +1,86 @@ +Title: (SLAM) Navigating While Mapping +URL: https://docs.nav2.org/tutorials/docs/navigation2_with_slam.html#launch-navigation2 +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This document explains how to use Nav2 with SLAM. +The following steps show ROS 2 users how to generate occupancy grid maps and use Nav2 to move their robot around. +This tutorial applies to both simulated and physical robots, but will be completed here on a physical robot. +Before completing this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Navigation2. +In this tutorial we’ll be using SLAM Toolbox. More information can be found in theROSCon talk for SLAM Toolbox + +## Requirements +You must install Navigation2, Turtlebot3, and SLAM Toolbox. +If you don’t have them installed, please followGetting Started. +SLAM Toolbox can be installed via: +or from built from source in your workspace with: + +## Tutorial Steps + + +## 0- Launch Robot Interfaces +For this tutorial, we will use the turtlebot3. +The turtlebot3 software can be installed via the following or on theturtlebot3 repository: +If you have another robot, replace with your robot specific interfaces. +Typically, this includes the robot state publisher of the URDF, simulated or physical robot interfaces, controllers, safety nodes, and the like. +Run the following commands first whenever you open a new terminal during this tutorial. +Launch your robot’s interface and robot state publisher, for example: + +## 1- Launch Navigation2 +Launch Navigation without nav2_amcl and nav2_map_server. +It is assumed that the SLAM node(s) will publish to /map topic and provide the map->odom transform. + +## 2- Launch SLAM +Bring up your choice of SLAM implementation. +Make sure it provides the map->odom transform and /map topic. +Run Rviz and add the topics you want to visualize such as /map, /tf, /laserscan etc. +For this tutorial, we will useSLAM Toolbox. + +## 3- Working with SLAM +Move your robot by requesting a goal through RViz or the ROS 2 CLI, ie: +You should see the map update live! To save this map to file: + +## 4- Getting Started Simplification +If you’re only interested in running SLAM in the turtlebot3 getting started sandbox world, we also provide a simple way to enable SLAM as a launch configuration. +Rather than individually launching the interfaces, navigation, and SLAM, you can continue to use thetb3_simulation_launch.pywithslamconfig set to true. +We provide the instructions above with the assumption that you’d like to run SLAM on your own robot which would have separated simulation / robot interfaces and navigation launch files that are combined intb3_simulation_launch.pyfor the purposes of easy testing. + +Code Examples: + +Language: unknown +File: gitclone-b-develgit@github.com:stevemacenski/slam_toolbox.git +``` +sudo +apt +install +ros--turtlebot3 +ros--turtlebot3-msgs +ros--turtlebot3-bringup + +``` + +Language: unknown +File: ros2launchslam_toolboxonline_async_launch.py +``` +ros2 +topic +pub +/goal_pose +geometry_msgs/PoseStamped +"{header: {stamp: {sec: 0}, frame_id: 'map'}, pose: {position: {x: 0.2, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}" +``` + +Language: unknown +File: tb3_simulation_launch.py +``` +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +slam: += +True + +``` diff --git "a/exported_docs/nav2/(STVL) Using an External Costmap Plugin\357\203\201.txt" "b/exported_docs/nav2/(STVL) Using an External Costmap Plugin\357\203\201.txt" new file mode 100644 index 0000000..df9abc0 --- /dev/null +++ "b/exported_docs/nav2/(STVL) Using an External Costmap Plugin\357\203\201.txt" @@ -0,0 +1,211 @@ +Title: (STVL) Using an External Costmap Plugin +URL: https://docs.nav2.org/tutorials/docs/navigation2_with_stvl.html#setup +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to load and use an external plugin. +This example uses theSpatio Temporal Voxel Layer(STVL) costmappluginlibplugin as an example. +STVL is a demonstrative pluginlib plugin and the same process can be followed for other costmap plugins as well as plugin planners, controllers, and behaviors. +Before completing this tutorial, please look at the previous two tutorials on navigation in simulation and physical hardware, if available. +This tutorial assumes knowledge of navigation and basic understanding of costmaps. + +## Costmap2D and STVL +Costmap 2D is the data object we use to buffer sensor information into a global view that the robot will use to create plans and control efforts. +Within Costmap2D, there are pluginlib plugin interfaces available to create custom behaviors loadable at runtime. +Examples of included pluginlib plugins for Costmap2D are the Obstacle Layer, Voxel Layer, Static Layer, and Inflation Layer. +However, these are simply example plugins offered by the base implementation. +Another available pluginlib plugin for Costmap2D in Navigation2 is STVL. +STVL is another 3D perception plugin similar to the Voxel Layer. +A more detailed overview of how it works can be foundin this repo, however it buffers 3D data from depth cameras, sonars, lidars, and more into a sparse volumetic world model and removes voxels over time proportional with a sensor model and time-based expiration. +This can be especially useful for robots in highly dynamic environments and decreases the resource utilization for 3D sensor processing by up to 2x. +STVL also treats 3D lidars and radars as first class citizens for support. +The ROSCon talk for STVL can be foundin this video. + +## Tutorial Steps + + +## 0- Setup +Follow the same process as inGetting Startedfor installing and setting up a robot for hardware testing or simulation, as applicable. Ensure ROS 2, Navigation2, and Gazebo are installed. + +## 1- Install STVL +STVL can be installed in ROS 2 via the ROS Build Farm: +It can also be built from source by cloning the repository into your Navigation2 workspace: + +## 1- Modify Navigation2 Parameter +STVL is an optional plugin, like all plugins, in Costmap2D. Costmap Plugins in Navigation2 are loaded in theplugin_namesandplugin_typesvariables inside of their respective costmaps. +For example, the following will load the static and obstacle layer plugins into the namestatic_layerandobstacle_layer, respectively: +To load the STVL plugin, a new plugin name and type must be added. +For example, if the application required an STVL layer and no obstacle layer, our file would be: +Similar to the Voxel Layer, after registering the plugin, we can add the configuration of the STVL layer under the namespacestvl_layer. +An example fully-described parameterization of an STVL configuration is: +Please copy-paste the text above, with theplugin_namesandplugin_typesregistration, into yournav2_params.yamlto enable STVL in your application. +Make sure to change both the local and global costmaps. +Note: Pluginlib plugins for other Navigation2 servers such as planning, behavior, and control can be set in this same way. + +## 2- Launch Navigation2 +Follow the same process as inGetting Startedto launch a simulated robot in gazebo with Navigation2. +Navigation2 is now using STVL as its 3D sensing costmap layer. + +## 3- RVIZ +With RViz open andpublish_voxel_map:true, you can visualize the underlying data structure’s 3D grid using the{local,global}_costmap/voxel_gridtopics. +Note: It is recommended in RViz to set thePointCloud2Size to your voxel size and the style toBoxeswith a neutral color for best visualization. + +Code Examples: + +Language: unknown +File: obstacle_layer +``` +global_costmap +: +global_costmap +: +ros__parameters +: +use_sim_time +: +True +plugins +: +[ +"static_layer" +, +"obstacle_layer" +] +``` + +Language: unknown +File: plugin:MyPlugin::Plugin +``` +global_costmap +: +global_costmap +: +ros__parameters +: +use_sim_time +: +True +plugins +: +[ +"static_layer" +, +"stvl_layer" +] +``` + +Language: unknown +File: stvl_layer +``` +stvl_layer +: +plugin +: +"spatio_temporal_voxel_layer/SpatioTemporalVoxelLayer" +enabled +: +true +voxel_decay +: +15. +decay_model +: +0 +voxel_size +: +0.05 +track_unknown_space +: +true +unknown_threshold +: +15 +mark_threshold +: +0 +update_footprint_enabled +: +true +combination_method +: +1 +origin_z +: +0.0 +publish_voxel_map +: +true +transform_tolerance +: +0.2 +mapping_mode +: +false +map_save_duration +: +60.0 +observation_sources +: +pointcloud +pointcloud +: +data_type +: +PointCloud2 +topic +: +/intel_realsense_r200_depth/points +marking +: +true +clearing +: +true +obstacle_range +: +3.0 +min_obstacle_height +: +0.0 +max_obstacle_height +: +2.0 +expected_update_rate +: +0.0 +observation_persistence +: +0.0 +inf_is_valid +: +false +filter +: +"voxel" +voxel_min_points +: +0 +clear_after_reading +: +true +max_z +: +7.0 +min_z +: +0.1 +vertical_fov_angle +: +0.8745 +horizontal_fov_angle +: +1.048 +decay_acceleration +: +15.0 +model_type +: +0 +``` diff --git "a/exported_docs/nav2/AMCL\357\203\201.txt" "b/exported_docs/nav2/AMCL\357\203\201.txt" new file mode 100644 index 0000000..cf67645 --- /dev/null +++ "b/exported_docs/nav2/AMCL\357\203\201.txt" @@ -0,0 +1,159 @@ +Title: AMCL +URL: https://docs.nav2.org/configuration/packages/configuring-amcl.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: first_map_only_ +``` +amcl +: +ros__parameters +: +alpha1 +: +0.2 +alpha2 +: +0.2 +alpha3 +: +0.2 +alpha4 +: +0.2 +alpha5 +: +0.2 +base_frame_id +: +"base_footprint" +beam_skip_distance +: +0.5 +beam_skip_error_threshold +: +0.9 +beam_skip_threshold +: +0.3 +do_beamskip +: +false +global_frame_id +: +"map" +lambda_short +: +0.1 +laser_likelihood_max_dist +: +2.0 +laser_max_range +: +100.0 +laser_min_range +: +-1.0 +laser_model_type +: +"likelihood_field" +max_beams +: +60 +max_particles +: +2000 +min_particles +: +500 +odom_frame_id +: +"odom" +pf_err +: +0.05 +pf_z +: +0.99 +recovery_alpha_fast +: +0.0 +recovery_alpha_slow +: +0.0 +resample_interval +: +1 +robot_model_type +: +"nav2_amcl::DifferentialMotionModel" +save_pose_rate +: +0.5 +sigma_hit +: +0.2 +tf_broadcast +: +true +transform_tolerance +: +1.0 +update_min_a +: +0.2 +update_min_d +: +0.25 +z_hit +: +0.5 +z_max +: +0.05 +z_rand +: +0.5 +z_short +: +0.05 +scan_topic +: +scan +map_topic +: +map +set_initial_pose +: +false +always_reset_initial_pose +: +false +first_map_only +: +false +initial_pose +: +x +: +0.0 +y +: +0.0 +z +: +0.0 +yaw +: +0.0 +``` diff --git "a/exported_docs/nav2/About and Contact\357\203\201.txt" "b/exported_docs/nav2/About and Contact\357\203\201.txt" new file mode 100644 index 0000000..0950624 --- /dev/null +++ "b/exported_docs/nav2/About and Contact\357\203\201.txt" @@ -0,0 +1,34 @@ +Title: About and Contact +URL: https://docs.nav2.org/about/index.html#contact +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## About +Navigation is a community effort to lower the barrier of entry of mobile robotics technology for all. +This project is one of the flagship projects along with MoveIt that acts as an applications entry point and frameworks for ROS. +Navigation in ROS 2 builds on the wild success of the original Navigation Stack (Nav Stack) in ROS (1). +This project has been used by researchers, educators, and industry for over 10 years. +There are very few projects that have lasted as long or were as successful as ROS (1) Navigation. +We would like to thank David Lu!! and Mike Ferguson for their tireless over the span of a decade to keep the Nav Stack alive and well. +Without their hard work, this project would not have been able to happen. +For a list of robots using Navigation2, seeRobots Using. +Aslas, as time moves on, so must we. +ROS (1) had a great run and those of us that build projects using it will remember it fondly(ish). +With change comes possibilities. +Navigation2 builds on the success but redesigns the framework to be more flexible and the feedback gathered over 10 years. +We strive to create an open community and encourage new ROS users and experts alike to collaborate. +However, that can’t happen without your issues, pull requests, and support. +Navigation, like all open-source projects, is kept going by a dedicated group of developers, maintainers, users, and collaborators. +We would like to thank here our current and past contributors and maintainers. +If you or your organization are interested in sponsoring Navigation or any work around it, please reach out to the current project lead. +Our current leadership team includes: +Our former leadership team includes: + +## Contact +If you are interested in contacting someone about Navigation, ROS 2, or related projects, please email the project leader or emailinfo@opennav.org. +We intentionally make our emails easy to find. +If your inquiry relates to bugs or open-source feature requests, consider posting a ticket on our GitHub project. +If your inquiry relates to configuration support or private feature development, reach out and we may be able to connect you with +independent consultants or contractors that know this project well. +Check out the Navigation 2Slackcommunity. diff --git "a/exported_docs/nav2/Adding a New Nav2 Task Server\357\203\201.txt" "b/exported_docs/nav2/Adding a New Nav2 Task Server\357\203\201.txt" new file mode 100644 index 0000000..3c69252 --- /dev/null +++ "b/exported_docs/nav2/Adding a New Nav2 Task Server\357\203\201.txt" @@ -0,0 +1,232 @@ +Title: Adding a New Nav2 Task Server +URL: https://docs.nav2.org/tutorials/docs/adding_a_nav2_task_server.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Lifecycle Nodes +The Lifecycle node is the first key component of a nav2 task server. Lifecycle nodes were introduced in ROS 2 to systematically manage the bringup and shutdown of the different nodes involved in the robot’s operation. The use of Lifecycle nodes ensures that all nodes are successfully instantiated before they begin their execution and Nav2 shuts down all nodes if there is any unresponsive node. +Lifecycle nodes contain state machine transitions that enable deterministic behavior in ROS 2 servers. The Lifecycle node transitions in Nav2 are handled by theLifecycleManager. The Lifecycle Manager transitions the states of the Lifecycle nodes and provides greater control over the state of a system. +The primary states of a Lifecycle node areUnconfigured,Inactive,Active, andFinalized. A Lifecycle node starts in anUnconfiguredstate after being instantiated. The Lifecycle Manager transitions a node fromUnconfiguredtoInactiveby implementing theConfiguratingtransition. TheConfiguratingtransition sets up all configuration parameters and prepares any required setup such as memory allocation and the set up of the static publication and subscription topics. A node in theInactivestate is allowed to reconfigure its parameters and but cannot perform any processing. From theInactivestate, the Lifecycle Manager implements theActivatingtransition state to transition the node fromInactivetoActive, which is the main state. A node in theActivestate is allowed to perform any processing operation. In case a node crashes, the Lifecycle Manager shuts down the system to prevent any critical failures. On shutdown, the necessary cleanup operations are performed and the nodes are transitioned to theFinalizedstate viaDeactivating,CleaningUp, andShuttingDowntransition states. +You may wish to integrate your own nodes into the Nav2 framework or add new lifecycle nodes to your system. As an example, we will add a new notional lifecycle nodesensor_driver, and have it be controlled via the Nav2 Lifecycle Manager to ensure sensor feeds are available before activating navigation. You can do so by adding asensor_drivernode in your launch file and adding it to the list of nodes to be activated by thelifecycle_managerbefore navigation, as shown in the example below. +In the snippet above, the nodes to be handled by the Lifecycle Manager are set using thenode_namesparameter. Thenode_namesparameter takes in an ordered list of nodes to bringup through the Lifecycle transition. As shown in the snippet, thenode_namesparameter takes inlifecycle_nodeswhich contains the list of nodes to be added to the Lifecycle Manager. The Lifecycle Manager implements bringup transitions (ConfiguringandActivating) to the nodes one-by-one and in order, while the nodes are processed in reverse order for shutdown transitions. Hence, thesensor_driveris listed first before the other navigation servers so that the sensor data is available before the navigation servers are activated. +Two other parameters of the Lifecycle Manager areautostartandbond_timeout. Setautostarttotrueif you want to set the transition nodes to theActivestate on startup. Otherwise, you will need to manually trigger Lifecycle Manager to transition up the system. Thebond_timeoutsets the waiting time to decide when to transition down all of the nodes if a node is not responding. + +## Composition +Composition is the second key component nav2 task servers that was introduced to reduce the memory and CPU resources by putting multiple nodes in a single process. In Nav2, Composition can be used to compose all Nav2 nodes in a single process instead of launching them separately. This is useful for deployment on embedded systems where developers need to optimize resource usage. +In the following section, we give an example on how to add a new Nav2 server, which we notionally call theroute_server, to our system. +We make use of the launch files to compose different servers into a single process. The process is established by theComposableNodeContainercontainer that is populated with composition nodes viaComposableNode. This container can then be launched and used the same as any other Nav2 node. + +## Error codes +Your nav2 task server may also wish to return a ‘error_code’ in its action response (though not required). If there are semantically meaningful and actionable types of failures for your system, this is a systemic way to communicate those failures which may be automatically aggregated into the responses of the navigation system to your application. +It is important to note that error codes from 0-9999 are reserved for internal nav2 servers with each server offset by 100 while external servers start at 10000 and end at 65535. +The table below shows the current servers along with the expected error code structure. +Error codes are attached to the response of the action message. An example can be seen below for the route server. Note that by convention we set the error code field within the message definition toerror_code. +As stated in the message, the priority order of the errors should match the message order, 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN. +Since the the route server is a external server, the errors codes start at 10000 and go up to 10099. +In order to propagate your server’s error code to the rest of the system it must be added to the nav2_params.yaml file. +Theerror_code_id_namesinside of the BT Navigator define what error codes to look for on the blackboard by the server. The lowest error code of the sequence is then returned - whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures. + +## Conclusion +In this section of the guide, we have discussed Lifecycle Nodes, Composition and Error Codes which are new and important concepts in ROS 2. We also showed how to implement Lifecycle Nodes, Composition and Error Codes to your newly created nodes/servers with Nav2. These three concepts are helpful to efficiently run your system and therefore are encouraged to be used throughout Nav2. + +Code Examples: + +Language: unknown +File: lifecycle_manager +``` +lifecycle_nodes += +[ +'sensor_driver' +, +'controller_server' +, +'smoother_server' +, +'planner_server' +, +'behavior_server' +, +'bt_navigator' +, +'waypoint_follower' +] +... +Node +( +package += +'nav2_sensor_driver' +, +executable += +'sensor_driver' +, +name += +'sensor_driver' +, +output += +'screen' +, +parameters += +[ +configured_params +], +remappings += +remappings +), +Node +( +package += +'nav2_lifecycle_manager' +, +executable += +'lifecycle_manager' +, +name += +'lifecycle_manager_navigation' +, +output += +'screen' +, +parameters += +[{ +'autostart' +: +autostart +}, +{ +'node_names' +: +lifecycle_nodes +}]), +``` + +Language: unknown +File: ComposableNode() +``` +container += +ComposableNodeContainer +( +name += +'my_container' +, +namespace += +'' +, +package += +'rclcpp_components' +, +executable += +'component_container' +, +composable_node_descriptions += +[ +ComposableNode +( +package += +'nav2_route_server' +, +plugin += +'nav2_route_server::RouteServer' +, +name += +'nav2_route_server' +), +], +output += +'screen' +, +) +``` + +Language: unknown +File: package.xml +``` + +nav2_route_server + +``` + +Language: unknown +File: error_code +``` +# Error codes +# Note: The expected priority order of the errors should match the message order + +uint16 +NONE += +0 +# 0 is reserved for NONE + +uint16 +UNKNOWN += +10000 +# first error code in the sequence is reserved for UNKNOWN +# User Error codes below + +int16 +INVALID_START += +10001 + +int16 +NO_VALID_ROUTE += +10002 +#goal definition + +route_msgs/PoseStamped +goal +route_msgs/PoseStamped +start +string +route_id +--- + +#result definition + +nav_msgs/Route +route +builtin_interfaces/Duration +route_time +uint16 +error_code +--- + +``` + +Language: unknown +File: error_code +``` +error_code_id_names +: +- +compute_path_error_code_id +- +follow_path_error_code_id +- +route_error_code_id +``` diff --git "a/exported_docs/nav2/Adding a Smoother to a BT\357\203\201.txt" "b/exported_docs/nav2/Adding a Smoother to a BT\357\203\201.txt" new file mode 100644 index 0000000..c9e5d2f --- /dev/null +++ "b/exported_docs/nav2/Adding a Smoother to a BT\357\203\201.txt" @@ -0,0 +1,140 @@ +Title: Adding a Smoother to a BT +URL: https://docs.nav2.org/tutorials/docs/adding_smoother.html#requirements +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to add a smoother to your behavior tree to smooth output paths from a path planner. +Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2. + +## Requirements +You must install Nav2, Turtlebot3. +If you don’t have them installed, please followGetting Started. +You must also have a working behavior tree, such as those provided by the Nav2 BT Navigator package, for editing. +You should also have a copy of thenav2_params.yamlfile for your system to edit as well. + +## Tutorial Steps + + +## 0- Familiarization with the Smoother BT Node +TheSmoothPathBT node is a behavior tree node that interacts with the smoother task server similar to that which you may expect to find for the planner or controller servers. It contains the action client to call the server and specifies its arguments and return types as BT ports. It too calls the server via an action interface that may be separately interacted with via other servers and client library languages. +Please see the BT node’s configuration page to familiarize yourself with all aspects, but the core ports to note are theunsmoothed_pathinput port and thesmoothed_pathoutput port. The first takes in a raw path from a planning algorithm and the latter will set the value of the smoothed output path post-smoothing. Other ports are available that fully implements the Smoother Server’s action API. + +## 1- Specifying a Smoother Plugin +In order to use a smoother in your BT node, you must first configure the smoother server itself to contain the smoother plugins of interest. These plugins implement the specific algorithms that you would like to use. +For each smoother plugin you would like to use, a name must be given to it (e.g.simple_smoother,curvature_smoother). This name is itssmoother_idfor other servers to interact with this algorithm from a request to the Smoother Server’s action interface. +Under each name, the parameters for that particular algorithm must be specified along with thepluginname for pluginlib to load a given algorithm’s library. An example configuration of 2 smoother plugins is shown below that could be used in thenav2_params.yamlfor your robot. + +## 2- Modifying your BT XML +Now that you have selected and configured the smoother server for your given plugin(s), it is time to use those smoother(s) in your behavior tree for navigation behavior. While there are many places / ways to use this in a BT, what is shown below is probably the most likely situation you would want to use the smoother in (to smooth a path returned by the path planner and then using that smoothed path for path tracking). +Note: If you use only a single type of smoothing algorithm, there is no need to specify thesmoother_idin the BT XML entry. Since there is only a single option, that will be used for any request that does not specifically request a smoother plugin. However, if you leverage multiple smoother plugins, youmustpopulate thesmoother_idXML port. +A given behavior tree will have a line: +This line calls the planner server and return a path to thepathblackboard variable in the behavior tree. We are going to replace that line with the following to compute the path, smooth the path, and finally replace thepathblackboard variable with the new smoothed path that the system will now interact with: +If you wish to have recoveries for the smoother error codes, such as triggering the system recoveries branch of a behavior tree: +And its as simple as that! You can now compile or use this behavior tree in your system and see that the plans are now smoothed and the controllers are now tracking this smoothed path. The image at the top of the tutorial shows the unsmoothed path from NavFn (red) and the smoothed path (black). Note the smoother approach to goal, turns, and transitions in the straight-line segments. +If you wish to see the difference, but not track the smoothed path, you may wish to remove thesmoothed_path="{path}"portion to compute the smoothed path, but not replace the original path with it. Instead, the topic/smoothed_pathcontains this information published by the smoother server for visualization or use by other parts of the system. You may also remap the smoothed path to another blackboard variable to interact with it in other parts of the behavior tree (e.g.smoothed_path="{smoothed_path}"). + +Code Examples: + +Language: unknown +File: nav2_params.yaml +``` +smoother_server +: +ros__parameters +: +costmap_topic +: +global_costmap/costmap_raw +footprint_topic +: +global_costmap/published_footprint +robot_base_frame +: +base_link +transform_timeout +: +0.1 +smoother_plugins +: +[ +"simple_smoother" +, +"curvature_smoother" +] +simple_smoother +: +plugin +: +"nav2_smoother::SimpleSmoother" +tolerance +: +1.0e-10 +do_refinement +: +True +curvature_smoother +: +plugin +: +"nav2_ceres_costaware_smoother/CeresCostawareSmoother" +``` + +Language: unknown +File: smoother_id +``` + +``` + +Language: unknown +File: path +``` + + + + +``` + +Language: unknown +File: path +``` + + + + +``` diff --git "a/exported_docs/nav2/AreErrorCodesPresent\357\203\201.txt" "b/exported_docs/nav2/AreErrorCodesPresent\357\203\201.txt" new file mode 100644 index 0000000..df2ade9 --- /dev/null +++ "b/exported_docs/nav2/AreErrorCodesPresent\357\203\201.txt" @@ -0,0 +1,36 @@ +Title: AreErrorCodesPresent +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/AreErrorCodesPresent.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example +Error codes to check are defined in another port. +Error codes to check are defined to be 101, 107 and 119. + +Code Examples: + +Language: unknown +File: FAILURE +``` + +``` + +Language: unknown +File: FAILURE +``` + +``` diff --git "a/exported_docs/nav2/AssistedTeleop\357\203\201.txt" "b/exported_docs/nav2/AssistedTeleop\357\203\201.txt" new file mode 100644 index 0000000..0df44b6 --- /dev/null +++ "b/exported_docs/nav2/AssistedTeleop\357\203\201.txt" @@ -0,0 +1,28 @@ +Title: AssistedTeleop +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/AssistedTeleop.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: AssistedTeleop +``` + +``` diff --git "a/exported_docs/nav2/BackUp\357\203\201.txt" "b/exported_docs/nav2/BackUp\357\203\201.txt" new file mode 100644 index 0000000..0bd2458 --- /dev/null +++ "b/exported_docs/nav2/BackUp\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: BackUp +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/BackUp.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: BackUp +``` + +``` diff --git "a/exported_docs/nav2/BaseObstacleCritic\357\203\201.txt" "b/exported_docs/nav2/BaseObstacleCritic\357\203\201.txt" new file mode 100644 index 0000000..2af9fd6 --- /dev/null +++ "b/exported_docs/nav2/BaseObstacleCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: BaseObstacleCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/base_obstacle.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: BaseObstacleCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/Behavior Server\357\203\201.txt" "b/exported_docs/nav2/Behavior Server\357\203\201.txt" new file mode 100644 index 0000000..a3b49ac --- /dev/null +++ "b/exported_docs/nav2/Behavior Server\357\203\201.txt" @@ -0,0 +1,167 @@ +Title: Behavior Server +URL: https://docs.nav2.org/configuration/packages/configuring-behavior-server.html#backup-behavior-parameters +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Behavior Server Parameters + + +## Default Plugins +When thebehavior_pluginsparameter is not overridden, the following default plugins are loaded: + +## Spin Behavior Parameters +Spin distance is given from the action request + +## BackUp Behavior Parameters +Backup distance, speed and time_allowance is given from the action request. + +## DriveOnHeading Behavior Parameters +DriveOnHeading distance, speed and time_allowance is given from the action request. + +## AssistedTeleop Behavior Parameters +AssistedTeleop time_allowance is given in the action request + +## Example + + +Code Examples: + +Language: unknown +File: plugin +``` +behavior_server +: +ros__parameters +: +behavior_plugins +: +[ +"spin" +, +"backup" +, +"drive_on_heading" +, +"wait" +] +spin +: +plugin +: +"nav2_behaviors::Spin" +# In Iron and older versions, "/" was used instead of "::" +backup +: +plugin +: +"nav2_behaviors::BackUp" +# In Iron and older versions, "/" was used instead of "::" +drive_on_heading +: +plugin +: +"nav2_behaviors::DriveOnHeading" +# In Iron and older versions, "/" was used instead of "::" +wait +: +plugin +: +"nav2_behaviors::Wait" +# In Iron and older versions, "/" was used instead of "::" +``` + +Language: unknown +File: TwistStamped +``` +behavior_server +: +ros__parameters +: +local_costmap_topic +: +local_costmap/costmap_raw +local_footprint_topic +: +local_costmap/published_footprint +global_costmap_topic +: +global_costmap/costmap_raw +global_footprint_topic +: +global_costmap/published_footprint +cycle_frequency +: +10.0 +behavior_plugins +: +[ +"spin" +, +"backup" +, +"drive_on_heading" +, +"wait" +, +"assisted_teleop" +] +spin +: +plugin +: +"nav2_behaviors::Spin" +# In Iron and older versions, "/" was used instead of "::" +backup +: +plugin +: +"nav2_behaviors::BackUp" +# In Iron and older versions, "/" was used instead of "::" +drive_on_heading +: +plugin +: +"nav2_behaviors::DriveOnHeading" +# In Iron and older versions, "/" was used instead of "::" +wait +: +plugin +: +"nav2_behaviors::Wait" +# In Iron and older versions, "/" was used instead of "::" +assisted_teleop +: +plugin +: +"nav2_behaviors::AssistedTeleop" +# In Iron and older versions, "/" was used instead of "::" +local_frame +: +odom +global_frame +: +map +robot_base_frame +: +base_link +transform_timeout +: +0.1 +simulate_ahead_time +: +2.0 +max_rotational_vel +: +1.0 +min_rotational_vel +: +0.4 +rotational_acc_lim +: +3.2 +enable_stamped_cmd_vel +: +true +# default false in Jazzy or older +``` diff --git "a/exported_docs/nav2/Behavior Tree XML Nodes\357\203\201.txt" "b/exported_docs/nav2/Behavior Tree XML Nodes\357\203\201.txt" new file mode 100644 index 0000000..8bf145f --- /dev/null +++ "b/exported_docs/nav2/Behavior Tree XML Nodes\357\203\201.txt" @@ -0,0 +1,149 @@ +Title: Behavior Tree XML Nodes +URL: https://docs.nav2.org/configuration/packages/configuring-bt-xml.html#decorator-plugins +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Action Plugins + + +## Condition Plugins + + +## Control Plugins + + +## Decorator Plugins + + +## Example +This Behavior Tree replans the global path periodically at 1 Hz and it also has +recovery actions. + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Behavior-Tree Navigator\357\203\201.txt" "b/exported_docs/nav2/Behavior-Tree Navigator\357\203\201.txt" new file mode 100644 index 0000000..91899c2 --- /dev/null +++ "b/exported_docs/nav2/Behavior-Tree Navigator\357\203\201.txt" @@ -0,0 +1,126 @@ +Title: Behavior-Tree Navigator +URL: https://docs.nav2.org/configuration/packages/configuring-bt-navigator.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: NavigateThroughPoses +``` +bt_navigator +: +ros__parameters +: +use_sim_time +: +true +global_frame +: +map +robot_base_frame +: +base_link +transform_tolerance +: +0.1 +default_nav_to_pose_bt_xml +: +replace/with/path/to/bt.xml +# or $(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml +default_nav_through_poses_bt_xml +: +replace/with/path/to/bt.xml +# or $(find-pkg-share my_package)/behavior_tree/my_nav_through_poses_bt.xml +always_reload_bt_xml +: +false +goal_blackboard_id +: +goal +goals_blackboard_id +: +goals +path_blackboard_id +: +path +navigators +: +[ +'navigate_to_pose' +, +'navigate_through_poses' +] +navigate_to_pose +: +plugin +: +"nav2_bt_navigator::NavigateToPoseNavigator" +# In Iron and older versions, "/" was used instead of "::" +navigate_through_poses +: +plugin +: +"nav2_bt_navigator::NavigateThroughPosesNavigator" +# In Iron and older versions, "/" was used instead of "::" +plugin_lib_names +: +- +nav2_compute_path_to_pose_action_bt_node +- +nav2_follow_path_action_bt_node +- +nav2_back_up_action_bt_node +- +nav2_spin_action_bt_node +- +nav2_wait_action_bt_node +- +nav2_clear_costmap_service_bt_node +- +nav2_is_stuck_condition_bt_node +- +nav2_is_stopped_condition_bt_node +- +nav2_goal_reached_condition_bt_node +- +nav2_initial_pose_received_condition_bt_node +- +nav2_goal_updated_condition_bt_node +- +nav2_reinitialize_global_localization_service_bt_node +- +nav2_rate_controller_bt_node +- +nav2_distance_controller_bt_node +- +nav2_speed_controller_bt_node +- +nav2_recovery_node_bt_node +- +nav2_pipeline_sequence_bt_node +- +nav2_round_robin_node_bt_node +- +nav2_transform_available_condition_bt_node +- +nav2_time_expired_condition_bt_node +- +nav2_distance_traveled_condition_bt_node +- +nav2_single_trigger_bt_node +error_code_names +: +- +compute_path_error_code +- +follow_path_error_code +# - smoother_error_code, navigate_to_pose_error_code, navigate_through_poses_error_code, etc +``` diff --git "a/exported_docs/nav2/Binary Filter Parameters\357\203\201.txt" "b/exported_docs/nav2/Binary Filter Parameters\357\203\201.txt" new file mode 100644 index 0000000..5463fa3 --- /dev/null +++ "b/exported_docs/nav2/Binary Filter Parameters\357\203\201.txt" @@ -0,0 +1,60 @@ +Title: Binary Filter Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/binary_filter.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: +``` +global_costmap +: +global_costmap +: +ros__parameters +: +... +plugins +: +[ +"static_layer" +, +"obstacle_layer" +, +"inflation_layer" +] +filters +: +[ +"binary_filter" +] +... +binary_filter +: +plugin +: +"nav2_costmap_2d::BinaryFilter" +enabled +: +True +filter_info_topic +: +"/costmap_filter_info" +transform_tolerance +: +0.1 +default_state +: +False +binary_state_topic +: +"/binary_state" +flip_threshold +: +50.0 +``` diff --git "a/exported_docs/nav2/Build Troubleshooting Guide\357\203\201.txt" "b/exported_docs/nav2/Build Troubleshooting Guide\357\203\201.txt" new file mode 100644 index 0000000..a1cfdf8 --- /dev/null +++ "b/exported_docs/nav2/Build Troubleshooting Guide\357\203\201.txt" @@ -0,0 +1,11 @@ +Title: Build Troubleshooting Guide +URL: https://docs.nav2.org/development_guides/build_docs/build_troubleshooting_guide.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Common Nav2 Dependencies Build Failures +Still can’t solve it? Let us know about your issue.Open a ticket. + +## Reporting Issue + diff --git "a/exported_docs/nav2/Build and Install\357\203\201.txt" "b/exported_docs/nav2/Build and Install\357\203\201.txt" new file mode 100644 index 0000000..66269e3 --- /dev/null +++ "b/exported_docs/nav2/Build and Install\357\203\201.txt" @@ -0,0 +1,198 @@ +Title: Build and Install +URL: https://docs.nav2.org/development_guides/build_docs/index.html#generate-doxygen +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Install +Nav2 and its dependencies are released as binaries. +You may install it via the following to get the latest stable released version: + +## For Iron and Older + + +## For Jazzy and Newer + + +## Build +There are a few ways to build Nav2 using: + +## Released Distribution Binaries +To build Nav2, you’ll first need to build or install ROS 2 and related development tools, including:colcon,rosdepandvcstool. +Once your environment is setup, clone the repo, install all dependencies, and build the workspace: +You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! + +## Rolling Development Source +Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages. +Nav2 does not currently release binaries on rolling, so it must be build from source. +Once your environment is setup, clone the repo and build the workspace: +You can thensource~/nav2_ws/install/setup.bashto get ready for demonstrations! It is safe +to ignore the rosdep error of from the missingslam_toolboxkey. + +## Docker Container Images +Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project’s Dockerfiles to build and install Nav2 for various distributions. +Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo: +Thedocker buildcommand above creates a tagged image using theDockerfilefrom the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set ofcolcon mixinsto configure the workspace build. Check theARGdirectives in theDockerfileto discover all build-time variables available. The command also specifies anexternal cache sourceto pull the latest cached image from Nav2’sContainer Registryto speed up the build process. + +## Generate Doxygen +Rundoxygenin the root of the Nav2 repository. +It will generate a/doc/*directory containing the documentation. +The documentation entrypoint in a browser is index.html. + +## Help +Build Troubleshooting Guide + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +source +/opt/ros//setup.bash +sudo +apt +install +\ +ros- +$ROS_DISTRO +-navigation2 +\ +ros- +$ROS_DISTRO +-nav2-bringup +\ +ros- +$ROS_DISTRO +-turtlebot3* + +``` + +Language: unknown +File: use_cancel_deceleration +``` +source +/opt/ros//setup.bash +sudo +apt +install +\ +ros- +$ROS_DISTRO +-navigation2 +\ +ros- +$ROS_DISTRO +-nav2-bringup +\ +ros- +$ROS_DISTRO +-nav2-minimal-tb* + +``` + +Language: unknown +File: main +``` +source +/opt/ros//setup.bash +mkdir +-p +~/nav2_ws/src +&& +cd +~/nav2_ws +git +clone +https://github.com/ros-navigation/navigation2.git +--branch +$ROS_DISTRO +./src/navigation2 +rosdep +install +-y +\ +--from-paths +./src +\ +--ignore-src +colcon +build +\ +--symlink-install + +``` + +Language: unknown +File: source~/nav2_ws/install/setup.bash +``` +source +/install/setup.bash +mkdir +-p +~/nav2_ws/src +&& +cd +~/nav2_ws +git +clone +https://github.com/ros-navigation/navigation2.git +--branch +main +./src/navigation2 +git +clone +https://github.com/ros-navigation/nav2_minimal_turtlebot_simulation.git +--branch +main +./src/nav2_minimal_turtlebot_simulation +rosdep +install +-r +-y +\ +--from-paths +./src +\ +--ignore-src +colcon +build +\ +--symlink-install + +``` + +Language: unknown +File: slam_toolbox +``` +export +ROS_DISTRO += +rolling +git +clone +https://github.com/ros-navigation/navigation2.git +--branch +main +docker +build +--tag +navigation2: +$ROS_DISTRO +\ +--build-arg +FROM_IMAGE += +ros: +$ROS_DISTRO +\ +--build-arg +OVERLAY_MIXINS += +"release ccache lld" +\ +--cache-from +ghcr.io/ros-navigation/navigation2:main +\ +./navigation2 + +``` diff --git "a/exported_docs/nav2/Camera Calibration\357\203\201.txt" "b/exported_docs/nav2/Camera Calibration\357\203\201.txt" new file mode 100644 index 0000000..16d2949 --- /dev/null +++ "b/exported_docs/nav2/Camera Calibration\357\203\201.txt" @@ -0,0 +1,261 @@ +Title: Camera Calibration +URL: https://docs.nav2.org/tutorials/docs/camera_calibration.html#tutorial-steps +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to obtain calibration parameters for monocular camera. + +## Requirements +1- Install Camera Calibration Parser, Camera Info Manager and Launch Testing Ament Cmake using operating system’s package manager: +2- Image Pipeline need to be built from source in your workspace with: +Also, make sure you have the following: + +## Tutorial Steps +1- Start a terminal in your GUI +2- Launch the ROS driver for your specific camera. +3- Make sure camera is publishing images over ROS. This can be tested by running: +4- This will show you all the topics published make sure that there is an image_raw topic /camera/image_raw. To confirm that its a real topic and actually publishing check topic hz: +5- Start the camera calibration node +6- In order to get a good calibration you will need to move the checkerboard around in the camera frame such that: +7- As the checkerboard is moved around the 4 bars on the calibration sidebar increases in length. When all then the 4 bars are green and enough data is available for calibration the CALIBRATE button will light up. Click it to see the results. It takes around the minute for calibration to take place. +8- After the calibration is completed the save and commit buttons light up. And you can also see the result in terminal. +9-Press the save button to see the result. Data is saved to “/tmp/calibrationdata.tar.gz” +11-In the folder images used for calibration are available and also “ost.yaml” and “ost.txt”. You can use the yaml file which contains the calibration parameters as directed by the camera driver. + +Code Examples: + +Language: unknown +File: ros2runcamera_calibrationcameracalibrator--size7x9--square0.02--ros-args-rimage:=/my_camera/image_raw-pcamera:=/my_camera +``` +Camera +Name +: +- +c +, +-- +camera_name +name +of +the +camera +to +appear +in +the +calibration +file +Chessboard +Options +: +You +must +specify +one +or +more +chessboards +as +pairs +of +-- +size +and +-- +square +options +. +- +p +PATTERN +, +-- +pattern += +PATTERN +calibration +pattern +to +detect +- +'chessboard' +, +'circles' +, +'acircles' +, +'charuco' +- +s +SIZE +, +-- +size += +SIZE +chessboard +size +as +NxM +, +counting +interior +corners +( +e +. +g +. +a +standard +chessboard +is +7 +x7 +) +- +q +SQUARE +, +-- +square += +SQUARE +chessboard +square +size +in +meters +ROS +Communication +Options +: +-- +approximate += +APPROXIMATE +allow +specified +slop +( +in +seconds +) +when +pairing +images +from +unsynchronized +stereo +cameras +-- +no +- +service +- +check +disable +check +for +set_camera_info +services +at +startup +Calibration +Optimizer +Options +: +-- +fix +- +principal +- +point +fix +the +principal +point +at +the +image +center +-- +fix +- +aspect +- +ratio +enforce +focal +lengths +( +fx +, +fy +) +are +equal +-- +zero +- +tangent +- +dist +set +tangential +distortion +coefficients +( +p1 +, +p2 +) +to +zero +- +k +NUM_COEFFS +, +-- +k +- +coefficients += +NUM_COEFFS +number +of +radial +distortion +coefficients +to +use +( +up +to +6 +, +default +2 +) +-- +disable_calib_cb_fast_check +uses +the +CALIB_CB_FAST_CHECK +flag +for +findChessboardCorners +This +will +open +a +calibration +window +which +highlight +the +checkerboard +. +``` diff --git "a/exported_docs/nav2/CancelAssistedTeleop\357\203\201.txt" "b/exported_docs/nav2/CancelAssistedTeleop\357\203\201.txt" new file mode 100644 index 0000000..03389a5 --- /dev/null +++ "b/exported_docs/nav2/CancelAssistedTeleop\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelAssistedTeleop +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelAssistedTeleop.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: assisted_teleop +``` + +``` diff --git "a/exported_docs/nav2/CancelBackUp\357\203\201.txt" "b/exported_docs/nav2/CancelBackUp\357\203\201.txt" new file mode 100644 index 0000000..cd7e3c5 --- /dev/null +++ "b/exported_docs/nav2/CancelBackUp\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelBackUp +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelBackUp.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: backup +``` + +``` diff --git "a/exported_docs/nav2/CancelControl\357\203\201.txt" "b/exported_docs/nav2/CancelControl\357\203\201.txt" new file mode 100644 index 0000000..385206b --- /dev/null +++ "b/exported_docs/nav2/CancelControl\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelControl +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelControl.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: server_name +``` + +``` diff --git "a/exported_docs/nav2/CancelCoverage\357\203\201.txt" "b/exported_docs/nav2/CancelCoverage\357\203\201.txt" new file mode 100644 index 0000000..cfe403d --- /dev/null +++ "b/exported_docs/nav2/CancelCoverage\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelCoverage +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelCoverage.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: server_name +``` + +``` diff --git "a/exported_docs/nav2/CancelDriveOnHeading\357\203\201.txt" "b/exported_docs/nav2/CancelDriveOnHeading\357\203\201.txt" new file mode 100644 index 0000000..81ca979 --- /dev/null +++ "b/exported_docs/nav2/CancelDriveOnHeading\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelDriveOnHeading +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelDriveOnHeading.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: drive_on_heading +``` + +``` diff --git "a/exported_docs/nav2/CancelSpin\357\203\201.txt" "b/exported_docs/nav2/CancelSpin\357\203\201.txt" new file mode 100644 index 0000000..0357243 --- /dev/null +++ "b/exported_docs/nav2/CancelSpin\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelSpin +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelSpin.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: spin +``` + +``` diff --git "a/exported_docs/nav2/CancelWait\357\203\201.txt" "b/exported_docs/nav2/CancelWait\357\203\201.txt" new file mode 100644 index 0000000..400c6f8 --- /dev/null +++ "b/exported_docs/nav2/CancelWait\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: CancelWait +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/CancelWait.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: wait +``` + +``` diff --git "a/exported_docs/nav2/ClearCostmapAroundRobot\357\203\201.txt" "b/exported_docs/nav2/ClearCostmapAroundRobot\357\203\201.txt" new file mode 100644 index 0000000..3c04a1a --- /dev/null +++ "b/exported_docs/nav2/ClearCostmapAroundRobot\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: ClearCostmapAroundRobot +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearCostmapAroundRobot.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/ClearCostmapExceptRegion\357\203\201.txt" "b/exported_docs/nav2/ClearCostmapExceptRegion\357\203\201.txt" new file mode 100644 index 0000000..f5b1bef --- /dev/null +++ "b/exported_docs/nav2/ClearCostmapExceptRegion\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: ClearCostmapExceptRegion +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearCostmapExceptRegion.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/ClearEntireCostmap\357\203\201.txt" "b/exported_docs/nav2/ClearEntireCostmap\357\203\201.txt" new file mode 100644 index 0000000..4373ec9 --- /dev/null +++ "b/exported_docs/nav2/ClearEntireCostmap\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: ClearEntireCostmap +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ClearEntireCostmap.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/Collision Detector Node\357\203\201.txt" "b/exported_docs/nav2/Collision Detector Node\357\203\201.txt" new file mode 100644 index 0000000..3ac3c8b --- /dev/null +++ "b/exported_docs/nav2/Collision Detector Node\357\203\201.txt" @@ -0,0 +1,116 @@ +Title: Collision Detector Node +URL: https://docs.nav2.org/configuration/packages/collision_monitor/configuring-collision-detector-node.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Features +Similarly to the Collision Monitor, the Collision Detector uses robot’s relative polygons to define “zones”. +However, unlike the Collision Monitor that uses different behavior models, the Collision Detector does not use any of them and therefore theaction_typeshould always be set tonone. If set to anything else, it will throw an error +The zones around the robot and the data sources are the same as for the Collision Monitor, with the exception of the footprint polygon, which is not supported by the Collision Detector. + +## Parameters + + +## Polygons parameters +is the corresponding polygon name ID selected for this type. + +## Observation sources parameters +is the corresponding data source name ID selected for this type. + +## Example +Here is an example of configuration YAML for the Collision Detector. + +Code Examples: + +Language: unknown +File: source_timeout:0.0 +``` +collision_detector +: +ros__parameters +: +base_frame_id +: +"base_footprint" +odom_frame_id +: +"odom" +transform_tolerance +: +0.5 +source_timeout +: +5.0 +base_shift_correction +: +True +polygons +: +[ +"PolygonFront" +] +PolygonFront +: +type +: +"polygon" +points +: +"[[0.3, +0.3], +[0.3, +-0.3], +[0.0, +-0.3], +[0.0, +0.3]]" +action_type +: +"none" +min_points +: +4 +visualize +: +True +polygon_pub_topic +: +"polygon_front" +observation_sources +: +[ +"scan" +] +scan +: +source_timeout +: +0.2 +type +: +"scan" +topic +: +"scan" +enabled +: +True +pointcloud +: +type +: +"pointcloud" +topic +: +"/intel_realsense_r200_depth/points" +min_height +: +0.1 +max_height +: +0.5 +enabled +: +True +``` diff --git "a/exported_docs/nav2/Collision Monitor Node\357\203\201.txt" "b/exported_docs/nav2/Collision Monitor Node\357\203\201.txt" new file mode 100644 index 0000000..9f1eb62 --- /dev/null +++ "b/exported_docs/nav2/Collision Monitor Node\357\203\201.txt" @@ -0,0 +1,379 @@ +Title: Collision Monitor Node +URL: https://docs.nav2.org/configuration/packages/collision_monitor/configuring-collision-monitor-node.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Features +The Collision Monitor uses polygons relative the robot’s base frame origin to define “zones”. +Data that fall into these zones trigger an operation depending on the model being used. +A given instance of the Collision Monitor can have many zones with different models at the same time. +When multiple zones trigger at once, the most aggressive one is used (e.g. stop > slow 50% > slow 10%). +The following models of safety behaviors are employed by Collision Monitor: +The zones around the robot can take the following shapes: +All shapes (Polygon,CircleandVelocityPolygon) are derived from basePolygonclass, so without loss of generality they would be called as “polygons”. +Subscribed footprint is also having the same properties as other polygons, but it is being obtained a footprint topic for the Approach Model. +The data may be obtained from different data sources: + +## Parameters + + +## Polygons parameters +is the corresponding polygon name ID selected for this type. + +## VelocityPolygon parameters +All previous Polygon parameters apply, in addition to the following unique parameters for VelocityPolygon. + +## Observation sources parameters +is the corresponding data source name ID selected for this type. + +## Example +Here is an example illustrating the common configurations for holonomic robots that cover multiple directions of the resultant velocity: +Here is an example of configuration YAML for the Collision Monitor. + +Code Examples: + +Language: unknown +File: source_timeout:0.0 +``` +collision_monitor +: +ros__parameters +: +base_frame_id +: +"base_footprint" +odom_frame_id +: +"odom" +cmd_vel_in_topic +: +"cmd_vel_smoothed" +cmd_vel_out_topic +: +"cmd_vel" +state_topic +: +"collision_monitor_state" +transform_tolerance +: +0.5 +source_timeout +: +5.0 +base_shift_correction +: +True +stop_pub_timeout +: +2.0 +enable_stamped_cmd_vel +: +True +# False for Jazzy or older +use_realtime_priority +: +false +polygons +: +[ +"PolygonStop" +, +"PolygonSlow" +, +"FootprintApproach" +] +PolygonStop +: +type +: +"circle" +radius +: +0.3 +action_type +: +"stop" +min_points +: +4 +# max_points: 3 for Humble +visualize +: +True +polygon_pub_topic +: +"polygon_stop" +enabled +: +True +PolygonSlow +: +type +: +"polygon" +points +: +"[[1.0, +1.0], +[1.0, +-1.0], +[-0.5, +-1.0], +[-0.5, +1.0]]" +action_type +: +"slowdown" +min_points +: +4 +# max_points: 3 for Humble +slowdown_ratio +: +0.3 +visualize +: +True +polygon_pub_topic +: +"polygon_slowdown" +enabled +: +True +PolygonLimit +: +type +: +"polygon" +points +: +"[[0.5, +0.5], +[0.5, +-0.5], +[-0.5, +-0.5], +[-0.5, +0.5]]" +action_type +: +"limit" +min_points +: +4 +# max_points: 3 for Humble +linear_limit +: +0.4 +angular_limit +: +0.5 +visualize +: +True +polygon_pub_topic +: +"polygon_limit" +enabled +: +True +FootprintApproach +: +type +: +"polygon" +action_type +: +"approach" +footprint_topic +: +"/local_costmap/published_footprint" +time_before_collision +: +2.0 +simulation_time_step +: +0.02 +min_points +: +6 +# max_points: 5 for Humble +visualize +: +False +enabled +: +True +VelocityPolygonStop +: +type +: +"velocity_polygon" +action_type +: +"stop" +min_points +: +6 +visualize +: +True +enabled +: +True +polygon_pub_topic +: +"velocity_polygon_stop" +velocity_polygons +: +[ +"rotation" +, +"translation_forward" +, +"translation_backward" +, +"stopped" +] +holonomic +: +false +rotation +: +points +: +"[[0.3, +0.3], +[0.3, +-0.3], +[-0.3, +-0.3], +[-0.3, +0.3]]" +linear_min +: +0.0 +linear_max +: +0.05 +theta_min +: +-1.0 +theta_max +: +1.0 +translation_forward +: +points +: +"[[0.35, +0.3], +[0.35, +-0.3], +[-0.2, +-0.3], +[-0.2, +0.3]]" +linear_min +: +0.0 +linear_max +: +1.0 +theta_min +: +-1.0 +theta_max +: +1.0 +translation_backward +: +points +: +"[[0.2, +0.3], +[0.2, +-0.3], +[-0.35, +-0.3], +[-0.35, +0.3]]" +linear_min +: +-1.0 +linear_max +: +0.0 +theta_min +: +-1.0 +theta_max +: +1.0 +# This is the last polygon to be checked, it should cover the entire range of robot's velocities +# It is used as the stopped polygon when the robot is not moving and as a fallback if the velocity +# is not covered by any of the other sub-polygons +stopped +: +points +: +"[[0.25, +0.25], +[0.25, +-0.25], +[-0.25, +-0.25], +[-0.25, +0.25]]" +linear_min +: +-1.0 +linear_max +: +1.0 +theta_min +: +-1.0 +theta_max +: +1.0 +observation_sources +: +[ +"scan" +, +"pointcloud" +] +scan +: +source_timeout +: +0.2 +type +: +"scan" +topic +: +"/scan" +enabled +: +True +pointcloud +: +type +: +"pointcloud" +topic +: +"/intel_realsense_r200_depth/points" +min_height +: +0.1 +max_height +: +0.5 +enabled +: +True +``` diff --git "a/exported_docs/nav2/Collision Monitor\357\203\201.txt" "b/exported_docs/nav2/Collision Monitor\357\203\201.txt" new file mode 100644 index 0000000..82e8077 --- /dev/null +++ "b/exported_docs/nav2/Collision Monitor\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Collision Monitor +URL: https://docs.nav2.org/configuration/packages/configuring-collision-monitor.html#provided-nodes +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Provided Nodes +The nodes listed below are inside thenav2_collision_monitorpackage. See the pages for individual configuration information. diff --git "a/exported_docs/nav2/ComputeCoveragePath\357\203\201.txt" "b/exported_docs/nav2/ComputeCoveragePath\357\203\201.txt" new file mode 100644 index 0000000..d527b1f --- /dev/null +++ "b/exported_docs/nav2/ComputeCoveragePath\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: ComputeCoveragePath +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputeCoveragePath.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example +Note: the blackboard IDs for the path, error code, and more may be adjusted,but need to match the corresponding parameters in theCoverageNavigatorplugin to set on the blackboard for use from the action server. + +Code Examples: + +Language: unknown +File: ComputeCoveragePath +``` + +``` diff --git "a/exported_docs/nav2/ComputePathThroughPoses\357\203\201.txt" "b/exported_docs/nav2/ComputePathThroughPoses\357\203\201.txt" new file mode 100644 index 0000000..f9aa4c1 --- /dev/null +++ "b/exported_docs/nav2/ComputePathThroughPoses\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: ComputePathThroughPoses +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputePathThroughPoses.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: ComputePathThroughPoses +``` + +``` diff --git "a/exported_docs/nav2/ComputePathToPose\357\203\201.txt" "b/exported_docs/nav2/ComputePathToPose\357\203\201.txt" new file mode 100644 index 0000000..a9dcd77 --- /dev/null +++ "b/exported_docs/nav2/ComputePathToPose\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: ComputePathToPose +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ComputePathToPose.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: ComputePathToPose +``` + +``` diff --git "a/exported_docs/nav2/Configuration Guide\357\203\201.txt" "b/exported_docs/nav2/Configuration Guide\357\203\201.txt" new file mode 100644 index 0000000..b0eeb0f --- /dev/null +++ "b/exported_docs/nav2/Configuration Guide\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Configuration Guide +URL: https://docs.nav2.org/configuration/index.html +Section: configuration/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/Constrained smoother\357\203\201.txt" "b/exported_docs/nav2/Constrained smoother\357\203\201.txt" new file mode 100644 index 0000000..e0d391f --- /dev/null +++ "b/exported_docs/nav2/Constrained smoother\357\203\201.txt" @@ -0,0 +1,106 @@ +Title: Constrained smoother +URL: https://docs.nav2.org/configuration/packages/configuring-constrained-smoother.html#smoother-server-parameters +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Smoother Server Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: DENSE_QR +``` +smoother_server +: +ros__parameters +: +use_sim_time +: +True +smoother_plugins +: +[ +"SmoothPath" +] +SmoothPath +: +plugin +: +"nav2_constrained_smoother/ConstrainedSmoother" +reversing_enabled +: +true +# whether to detect forward/reverse direction and cusps. Should be set to false for paths without orientations assigned +path_downsampling_factor +: +3 +# every n-th node of the path is taken. Useful for speed-up +path_upsampling_factor +: +1 +# 0 - path remains downsampled, 1 - path is upsampled back to original granularity using cubic bezier, 2... - more upsampling +keep_start_orientation +: +true +# whether to prevent the start orientation from being smoothed +keep_goal_orientation +: +true +# whether to prevent the gpal orientation from being smoothed +minimum_turning_radius +: +0.40 +# minimum turning radius the robot can perform. Can be set to 0.0 (or w_curve can be set to 0.0 with the same effect) for diff-drive/holonomic robots +w_curve +: +30.0 +# weight to enforce minimum_turning_radius +w_dist +: +0.0 +# weight to bind path to original as optional replacement for cost weight +w_smooth +: +2000000.0 +# weight to maximize smoothness of path +w_cost +: +0.015 +# weight to steer robot away from collision and cost +# Parameters used to improve obstacle avoidance near cusps (forward/reverse movement changes) +w_cost_cusp_multiplier +: +3.0 +# option to use higher weight during forward/reverse direction change which is often accompanied with dangerous rotations +cusp_zone_length +: +2.5 +# length of the section around cusp in which nodes use w_cost_cusp_multiplier (w_cost rises gradually inside the zone towards the cusp point, whose costmap weight eqals w_cost*w_cost_cusp_multiplier) +# Points in robot frame to grab costmap values from. Format: [x1, y1, weight1, x2, y2, weight2, ...] +# IMPORTANT: Requires much higher number of iterations to actually improve the path. Uncomment only if you really need it (highly elongated/asymmetric robots) +# cost_check_points: [-0.185, 0.0, 1.0] +optimizer +: +max_iterations +: +70 +# max iterations of smoother +debug_optimizer +: +false +# print debug info +gradient_tol +: +5e3 +fn_tol +: +1.0e-15 +param_tol +: +1.0e-20 +``` diff --git "a/exported_docs/nav2/Controller Server\357\203\201.txt" "b/exported_docs/nav2/Controller Server\357\203\201.txt" new file mode 100644 index 0000000..096764e --- /dev/null +++ "b/exported_docs/nav2/Controller Server\357\203\201.txt" @@ -0,0 +1,154 @@ +Title: Controller Server +URL: https://docs.nav2.org/configuration/packages/configuring-controller-server.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Provided Plugins + + +## Default Plugins +When theprogress_checker_plugins,goal_checker_pluginorcontroller_pluginsparameters are not overridden, the following default plugins are loaded: + +## Example + + +Code Examples: + +Language: unknown +File: plugin +``` +controller_server +: +ros__parameters +: +controller_plugins +: +[ +"FollowPath" +] +FollowPath +: +plugin +: +"dwb_core::DWBLocalPlanner" +``` + +Language: unknown +File: plugin +``` +controller_server +: +ros__parameters +: +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +``` + +Language: unknown +File: plugin +``` +controller_server +: +ros__parameters +: +goal_checker_plugins +: +[ +"goal_checker" +] +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +``` + +Language: unknown +File: controller_plugins +``` +controller_server +: +ros__parameters +: +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +failure_tolerance +: +0.3 +odom_topic +: +"odom" +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +goal_checker_plugins +: +[ +"goal_checker" +] +# goal_checker_plugin: "goal_checker" For Galactic and older +controller_plugins +: +[ +"FollowPath" +] +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +required_movement_radius +: +0.5 +movement_time_allowance +: +10.0 +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +stateful +: +True +FollowPath +: +plugin +: +"dwb_core::DWBLocalPlanner" +``` diff --git "a/exported_docs/nav2/ControllerSelector\357\203\201.txt" "b/exported_docs/nav2/ControllerSelector\357\203\201.txt" new file mode 100644 index 0000000..2862c3e --- /dev/null +++ "b/exported_docs/nav2/ControllerSelector\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: ControllerSelector +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ControllerSelector.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: transientlocal +``` + +``` diff --git "a/exported_docs/nav2/Costmap 2D\357\203\201.txt" "b/exported_docs/nav2/Costmap 2D\357\203\201.txt" new file mode 100644 index 0000000..914d90c --- /dev/null +++ "b/exported_docs/nav2/Costmap 2D\357\203\201.txt" @@ -0,0 +1,330 @@ +Title: Costmap 2D +URL: https://docs.nav2.org/configuration/packages/configuring-costmaps.html#default-plugins +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Costmap2D ROS Parameters + + +## Default Plugins +When thepluginsparameter is not overridden, the following default plugins are loaded: + +## Plugin Parameters + + +## Costmap Filters Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: plugin +``` +local_costmap +: +ros__parameters +: +plugins +: +[ +"obstacle_layer" +, +"voxel_layer" +, +"inflation_layer" +] +obstacle_layer +: +plugin +: +"nav2_costmap_2d::ObstacleLayer" +voxel_layer +: +plugin +: +"nav2_costmap_2d::VoxelLayer" +inflation_layer +: +plugin +: +"nav2_costmap_2d::InflationLayer" +``` + +Language: unknown +File: plugin +``` +local_costmap +: +ros__parameters +: +filters +: +[ +"keepout_filter" +, +"speed_filter" +] +keepout_filter +: +plugin +: +"nav2_costmap_2d::KeepoutFilter" +speed_filter +: +plugin +: +"nav2_costmap_2d::SpeedFilter" +``` + +Language: unknown +File: plugins +``` +global_costmap +: +global_costmap +: +ros__parameters +: +footprint_padding +: +0.03 +update_frequency +: +1.0 +publish_frequency +: +1.0 +global_frame +: +map +robot_base_frame +: +base_link +use_sim_time +: +True +robot_radius +: +0.22 +# radius set and used, so no footprint points +resolution +: +0.05 +plugins +: +[ +"static_layer" +, +"obstacle_layer" +, +"voxel_layer" +, +"inflation_layer" +] +obstacle_layer +: +plugin +: +"nav2_costmap_2d::ObstacleLayer" +enabled +: +True +observation_sources +: +scan +footprint_clearing_enabled +: +true +max_obstacle_height +: +2.0 +combination_method +: +1 +scan +: +topic +: +/scan +obstacle_max_range +: +2.5 +obstacle_min_range +: +0.0 +raytrace_max_range +: +3.0 +raytrace_min_range +: +0.0 +max_obstacle_height +: +2.0 +min_obstacle_height +: +0.0 +clearing +: +True +marking +: +True +data_type +: +"LaserScan" +inf_is_valid +: +false +voxel_layer +: +plugin +: +"nav2_costmap_2d::VoxelLayer" +enabled +: +True +footprint_clearing_enabled +: +true +max_obstacle_height +: +2.0 +publish_voxel_map +: +True +origin_z +: +0.0 +z_resolution +: +0.05 +z_voxels +: +16 +max_obstacle_height +: +2.0 +unknown_threshold +: +15 +mark_threshold +: +0 +observation_sources +: +pointcloud +combination_method +: +1 +pointcloud +: +# no frame set, uses frame from message +topic +: +/intel_realsense_r200_depth/points +max_obstacle_height +: +2.0 +min_obstacle_height +: +0.0 +obstacle_max_range +: +2.5 +obstacle_min_range +: +0.0 +raytrace_max_range +: +3.0 +raytrace_min_range +: +0.0 +clearing +: +True +marking +: +True +data_type +: +"PointCloud2" +static_layer +: +plugin +: +"nav2_costmap_2d::StaticLayer" +map_subscribe_transient_local +: +True +enabled +: +true +subscribe_to_updates +: +true +transform_tolerance +: +0.1 +inflation_layer +: +plugin +: +"nav2_costmap_2d::InflationLayer" +enabled +: +true +inflation_radius +: +0.55 +cost_scaling_factor +: +1.0 +inflate_unknown +: +false +inflate_around_unknown +: +true +always_send_full_costmap +: +True +local_costmap +: +local_costmap +: +ros__parameters +: +update_frequency +: +5.0 +publish_frequency +: +2.0 +global_frame +: +odom +robot_base_frame +: +base_link +use_sim_time +: +True +rolling_window +: +true +width +: +3 +height +: +3 +resolution +: +0.05 +``` diff --git "a/exported_docs/nav2/Coverage Server\357\203\201.txt" "b/exported_docs/nav2/Coverage Server\357\203\201.txt" new file mode 100644 index 0000000..8df97db --- /dev/null +++ "b/exported_docs/nav2/Coverage Server\357\203\201.txt" @@ -0,0 +1,64 @@ +Title: Coverage Server +URL: https://docs.nav2.org/configuration/packages/configuring-coverage-server.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: opennav_row_coverage +``` +coverage_server +: +ros__parameters +: +action_server_result_timeout +: +10.0 +coordinates_in_cartesian_frame +: +true +robot_width +: +2.1 +operation_width +: +2.5 +min_turning_radius +: +0.4 +linear_curv_change +: +2.0 +default_allow_overlap +: +true +default_headland_width +: +0.5 +default_path_continuity_type +: +"CONTINUOUS" +default_path_type +: +"DUBINS" +default_route_type +: +"BOUSTROPHEDON" +default_swath_angle_type +: +"BRUTE_FORCE" +default_swath_type +: +"LENGTH" +default_turn_point_distance +: +0.1 +``` diff --git "a/exported_docs/nav2/DWB Controller\357\203\201.txt" "b/exported_docs/nav2/DWB Controller\357\203\201.txt" new file mode 100644 index 0000000..efe67e6 --- /dev/null +++ "b/exported_docs/nav2/DWB Controller\357\203\201.txt" @@ -0,0 +1,219 @@ +Title: DWB Controller +URL: https://docs.nav2.org/configuration/packages/configuring-dwb-controller.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Controller + + +## Plugins +The plugins listed below are inside thedwb_pluginsnamespace. + +## Trajectory Critics +The trajectory critics listed below are inside thedwb_criticsnamespace. + +## Example + + +Code Examples: + +Language: unknown +File: dwb_critics +``` +controller_server +: +ros__parameters +: +# controller server parameters (see Controller Server for more info) +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +goal_checker_plugins +: +[ +"goal_checker" +] +controller_plugins +: +[ +"FollowPath" +] +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +required_movement_radius +: +0.5 +movement_time_allowance +: +10.0 +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +stateful +: +True +# DWB controller parameters +FollowPath +: +plugin +: +"dwb_core::DWBLocalPlanner" +debug_trajectory_details +: +True +min_vel_x +: +0.0 +min_vel_y +: +0.0 +max_vel_x +: +0.26 +max_vel_y +: +0.0 +max_vel_theta +: +1.0 +min_speed_xy +: +0.0 +max_speed_xy +: +0.26 +min_speed_theta +: +0.0 +acc_lim_x +: +2.5 +acc_lim_y +: +0.0 +acc_lim_theta +: +3.2 +decel_lim_x +: +-2.5 +decel_lim_y +: +0.0 +decel_lim_theta +: +-3.2 +vx_samples +: +20 +vy_samples +: +5 +vtheta_samples +: +20 +sim_time +: +1.7 +linear_granularity +: +0.05 +angular_granularity +: +0.025 +transform_tolerance +: +0.2 +xy_goal_tolerance +: +0.25 +trans_stopped_velocity +: +0.25 +short_circuit_trajectory_evaluation +: +True +limit_vel_cmd_in_traj +: +False +stateful +: +True +critics +: +[ +"RotateToGoal" +, +"Oscillation" +, +"BaseObstacle" +, +"GoalAlign" +, +"PathAlign" +, +"PathDist" +, +"GoalDist" +] +BaseObstacle.scale +: +0.02 +PathAlign.scale +: +32.0 +GoalAlign.scale +: +24.0 +PathAlign.forward_point_distance +: +0.1 +GoalAlign.forward_point_distance +: +0.1 +PathDist.scale +: +32.0 +GoalDist.scale +: +24.0 +RotateToGoal.scale +: +32.0 +RotateToGoal.slowing_factor +: +5.0 +RotateToGoal.lookahead_time +: +-1.0 +``` diff --git "a/exported_docs/nav2/Dashing to Eloquent\357\203\201.txt" "b/exported_docs/nav2/Dashing to Eloquent\357\203\201.txt" new file mode 100644 index 0000000..4a4f49c --- /dev/null +++ "b/exported_docs/nav2/Dashing to Eloquent\357\203\201.txt" @@ -0,0 +1,40 @@ +Title: Dashing to Eloquent +URL: https://docs.nav2.org/migration/Dashing.html#new-packages +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## New Packages +Navigation2 now includes a new packagenav2_waypoint_follower. +The waypoint follower is an action server that will take in a list of waypoints to follow and follow them in order. +There is a parameterstop_on_failurewhether the robot should continue to the next waypoint on a single waypoint failure, +or to return fail to the action client. +The waypoint follower is also a reference application for how to use the Navigation2 action server to complete a basic autonomy task. +Navigation2 now supports new algorithms for control and SLAM. +The Timed-Elastic Band (TEB) controller was implementedand can be found here. +It is its own controller plugin that can be used instead of the DWB controller. +Nav2 also supports SLAM Toolbox as the default SLAM implementation for ROS 2. +This replaces the use of Cartographer. + +## New Plugins +Eloquent introduces back in pluginlib plugins to the navigation stack.nav2_coredefines the plugin header interfaces to be used to implement controller, planner, recovery, and goal checker plugins. +All algorithms (NavFn, DWB, recoveries) were added as plugin interfaces and the general packages for servers were created.nav2_planneris the action server for planning that hosts a plugin for the planner.nav2_controlleris the action server for controller that hosts a plugin for the controller.nav2_recoveryis the action server for recovery that hosts a plugin for recovery. +New recovery plugins were added including backup, which will take in a distance to back up, if collision-free. +Additionally, the wait recovery was added that will wait a configurable period of time before trying to navigate again. +This plugin is especially helpful for time-dependent obstacles or pausing navigation for a scene to become less dynamic. +Many new behavior tree nodes were added. These behavior tree nodes are hard-coded in the behavior tree engine. +Behavior tree cpp v3 supports plugins and will be converted in the next release. + +## Navigation2 Architectural Changes +Thenav2_world_modelpackage was removed. The individualnav2_plannerandnav2_controllerservers now host their relevant costmaps. +This was done to reduce network traffic and ensure up-to-date information for the safety-critical elements of the system. +As above mentions, plugins were introduced into the stack and these servers each host plugins for navigation, control, and costmap layers. +Map server was substantially refactored but the external API remains the same. It now uses the SDL library for image loading. +TF-based positioning is now used for pose-estimation everywhere in the stack. +Prior, some elements of the navigation stack only updated its pose from the/amcl_posetopic publishing at an irregular rate. +This is obviously low-accuracy and high-latency. +All positioning is now based on the TF tree from the global frame to the robot frame. +Prior to Eloquent, there were no ROS 2 action servers and clients available. +Navigation2, rather, used an interface we called Tasks. +Eloquent now contains actions and a simple action server interface was created and is used now throughout the stack. +Tasks were removed. diff --git "a/exported_docs/nav2/Denoise Layer Parameters\357\203\201.txt" "b/exported_docs/nav2/Denoise Layer Parameters\357\203\201.txt" new file mode 100644 index 0000000..e520bbc --- /dev/null +++ "b/exported_docs/nav2/Denoise Layer Parameters\357\203\201.txt" @@ -0,0 +1,46 @@ +Title: Denoise Layer Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/denoise.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: +``` +local_costmap +: +local_costmap +: +ros__parameters +: +... +plugins +: +[ +"voxel_layer" +, +"denoise_layer" +, +"inflation_layer" +] +... +denoise_layer +: +plugin +: +"nav2_costmap_2d::DenoiseLayer" +enabled +: +true +minimal_group_size +: +2 +group_connectivity_type +: +8 +``` diff --git "a/exported_docs/nav2/Detailed Behavior Tree Walkthrough\357\203\201.txt" "b/exported_docs/nav2/Detailed Behavior Tree Walkthrough\357\203\201.txt" new file mode 100644 index 0000000..1124428 --- /dev/null +++ "b/exported_docs/nav2/Detailed Behavior Tree Walkthrough\357\203\201.txt" @@ -0,0 +1,313 @@ +Title: Detailed Behavior Tree Walkthrough +URL: https://docs.nav2.org/behavior_trees/overview/detailed_behavior_tree_walkthrough.html#prerequisites +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This document serves as a reference guide to the main behavior tree (BT) used in Nav2. +There are many example behavior trees provided innav2_bt_navigator/behavior_trees, +but these sometimes have to be re-configured based on the application of the robot. +The following document will walk through the current main default BTnavigate_to_pose_w_replanning_and_recovery.xmlin great detail. + +## Prerequisites + + +## Navigate To Pose With Replanning and Recovery +The following section will describe in detail the concept of the main and default BT currently used in Nav2,navigate_to_pose_w_replanning_and_recovery.xml. +This behavior tree replans the global path periodically at 1 Hz and it also has recovery actions. +BTs are primarily defined in XML. The tree shown above is represented in XML as follows. +This is likely still a bit overwhelming, but this tree can be broken into two smaller subtrees that we can focus on one at a time. +These smaller subtrees are the children of the top-mostRecoveryNode. From this point forward theNavigateWithReplanningsubtree will be referred to as theNavigationsubtree, and theRecoveryFallbacksubtree will be known as theRecoverysubtree. +This can be represented in the following way: +TheNavigationsubtree mainly involves actual navigation behavior: +TheRecoverysubtree includes behaviors for system level failures or items that were not easily dealt with internally. +The overall BT will (hopefully) spend most of its time in theNavigationsubtree. If either of the two main behaviors in theNavigationsubtree fail +(path calculation or path following), contextual recoveries will be attempted. +If the contextual recoveries were still not enough, theNavigationsubtree will returnFAILURE. +The system will move on to theRecoverysubtree to attempt to clear any system level navigation failures. +This happens until thenumber_of_retriesfor the parentRecoveryNodeis exceeded (which by default is 6). + +## Navigation Subtree +Now that we have gone over the control flow between theNavigationsubtree and theRecoverysubtree, let’s focus on the Navigation subtree. +The XML of this subtree is as follows: +This subtree has two primary actionsComputePathToPoseandFollowPath. +If either of these two actions fail, they will attempt to clear the failure contextually. +The crux of the tree can be represented with only one parent and two children nodes like this: +The parentPipelineSequencenode allows theComputePathToPoseto be ticked, and once that succeeds,FollowPathto be ticked. +While theFollowPathsubtree is being ticked, theComputePathToPosesubtree will be ticked as well. This allows for the path to be recomputed as the robot moves around. +Both theComputePathToPoseand theFollowPathfollow the same general structure. +The below is theComputePathToPosesubtree: +The parentRecoveryNodecontrols the flow between the action, and the contextual recovery subtree. +The contextual recoveries for bothComputePathToPoseandFollowPathinvolve checking if the goal has been updated, and involves clearing the relevant costmap. +Consider changing thenumber_of_retriesparameter in the parentRecoveryNodecontrol node if your application can tolerate more attempts at contextual recoveries before moving on to system-level recoveries. +The only differences in the BT subtree ofComputePathToPoseandFollowPathare outlined below: + +## Recovery Subtree +TheRecoverysubtree is the second big “half” of the Nav2 defaultnavigate_to_pose_w_replanning_and_recovery.xmltree. +In short, this subtree is triggered when theNavigationsubtree returnsFAILUREand controls the recoveries at the system level (in the case the contextual recoveries in theNavigationsubtree were not sufficient). +And the XML snippet: +The top most parent,ReactiveFallbackcontrols the flow between the rest of the system wide recoveries, and asynchronously checks if a new goal has been received. +If at any point the goal gets updated, this subtree will halt all children and returnSUCCESS. This allows for quick reactions to new goals and preempt currently executing recoveries. +This should look familiar to the contextual recovery portions of theNavigationsubtree. This is a common BT pattern to handle the situation “Unless ‘this condition’ happens, Do action A”. +These condition nodes can be extremely powerful and are typically paired withReactiveFallback. It can be easy to imagine wrapping this wholenavigate_to_pose_w_replanning_and_recoverytree +in aReactiveFallbackwith aisBatteryLowcondition – meaning thenavigate_to_pose_w_replanning_and_recoverytree will executeunlessthe battery becomes low (and then enter a different subtree for docking to recharge). +If the goal is never updated, the behavior tree will go on to theRoundRobinnode. These are the default four system-level recoveries in the BT are: +UponSUCCESSof any of the four children of the parentRoundRobin, the robot will attempt to renavigate in theNavigationsubtree. +If this renavigation was not successful, the next child of theRoundRobinwill be ticked. +For example, let’s say the robot is stuck and theNavigationsubtree returnsFAILURE: +(for the sake of this example, let’s assume that the goal is never updated). +If theBackUpaction was not sufficient enough to allow the robot to become un-stuck, the above logic will go on indefinitely until thenumber_of_retriesin the parent of theNavigatesubtree andRecoverysubtree is exceeded, or if all the system-wide recoveries in theRecoverysubtree returnFAILURE(this is unlikely, and likely points to some other system failure). + +Code Examples: + +Language: unknown +File: navigate_to_pose_w_replanning_and_recovery.xml +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +Language: unknown +File: RecoveryNode +``` + +``` + +Language: unknown +File: Recovery +``` + + + + + + + + + + + + + + + + + + +``` + +Language: unknown +File: Navigation +``` + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Dev Container Guide\357\203\201.txt" "b/exported_docs/nav2/Dev Container Guide\357\203\201.txt" new file mode 100644 index 0000000..134a51c --- /dev/null +++ "b/exported_docs/nav2/Dev Container Guide\357\203\201.txt" @@ -0,0 +1,64 @@ +Title: Dev Container Guide +URL: https://docs.nav2.org/development_guides/devcontainer_docs/devcontainer_guide.html#creating-dev-containers +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Creating Dev Containers +Before creating a dev container, you’ll want to choose the exact configuration to use. By default the.devcontainer/devcontainer.jsonconfiguration is selected, however you can also choose any otherdevcontainer.jsonfile in the.devcontainer/directory, where such configurations can be nested to provide greater customization: either by targeting different stages within different Dockerfiles, overriding any merged metadata or default properties, or inclusion of additional extensions and alternate commands. + +## Building the image +When first creating Dev Containers, any supporting tool or service used will download and build the docker images needed to run the container. This includes pulling any parent images the project’s Dockerfile buildsFROM, as well as any tags or layers declared viacacheFrom, as specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until such layers are updated and pushed to the image registry. +Specifically, for this project, the defaultdevcontainer.jsonfile targets thedeverstage within the project’s root Dockerfile, the stage that also includes handy tools for developing the project, such as bash auto completion. This stage is in turn builtFROMthebuilderstage, the stage that only includes the dependencies needed for building the project, as reused by the project’s CI. For example, thedeverstage modifies/etc/bash.bashrcto automatically sourceinstall/setup.bashfrom the underlay workspace, ensuring all VS Code extensions are loaded with the correct environment, while avoiding any race conditions during installation and startup. +To speed up the initial build, images layers from thisbuilderstage are cached by pulling the same image tag used by the project’s CI, hosted from the image registry. This ensures your local dev container replicates our CI environment as close as possible, while benefiting from any cached work preemptively performed by the CI. Yet, this still allows you to customize the project’s Dockerfile and rebuild the container, without needing to update CI images to reflect your local modifications. +Once the base image from the target stage is built, the supporting tool or service may then add additional layers to the image, such as installing additionalfeaturesor customizations. For VS Code, this also includes some fancy file caching for any extensions to install later. Once this custom image is built, it is then used to start the dev container. + +## Starting the container +When first creating Dev Containers, any supporting tool or service will invoke a sequence of commands specified in the chosendevcontainer.jsonconfig file. This can take a while, but only needs to be done once, or at least not again until the container is rebuilt, triggered by either updating the Dockerfile, base image, or.devcontainer/config. +Specifically, for this project, the defaultdevcontainer.jsonconfig executes theonCreateCommandto initially colcon cache, clean, and build the overlay workspace for the project. This ensures the workspace is precompiled and ready to use, while also ensuring any changes to the project’s source code are reflected in the container. This is useful for: +While the colcon workspace is being built, VS Code will simultaneously install any specified extensions and settings. Next theupdateContentCommandis executed, which reruns whenever the container is started or restarted. Specifically, for this project, this command re-cleans and re-builds the same colcon workspace as before, but only for invalidated packages detected by colcon cache using the lockfiles initialized during theonCreateCommand. This caching behavior also replicates the project’s CI workflow. This is useful for: +Finally, thepostCreateCommandis executed, which also reruns whenever the container is started or restarted. Specifically, for this project, this command makes a last few tweaks to the user’s environment to improve the development experience. +To speed up subsequent startups, volumes that are mounted to the container store a persistent ccache and colcon workspace, while the environment is set to enableccacheviacolcon mixins. These volumes are labeled using thedevcontainerIdvariable, which uniquely identify the dev container on a Docker host, allowing us to refer to a common identifier that is unique to the dev container, while remaining stable across rebuilds. This is useful for: +Additionally, the container can be grantedprivilegedand non-defaultLinux capabilities, connected using thehostnetwork mode andIPCandPIDspaces, with a relaxedsecurity configurationand seccomp confinement for native debugging and external connectivity. This is useful for: + +## Using Dev Containers +Once the dev container has been created and setup completed, VS Code will open a new workspace directly from the project’s root directory, which itself is mounted within the source directory in the overlay colcon workspace. From here you can build, test, and debug the project as you normally would, with the added benefit of having the project’s dependencies, intellisense, linters, and other extensions pre-configured and ready to use. Simply open a new terminal (Crtl+Shift+`), cd to the root of the colcon workspace, and run the usual colcon commands. + +## Terminals +If you prefer using an alternate terminal emulator, rather than the built-in VS Code terminal, you can open a separate shell session by simply using the Dev Container CLI or directly using the Docker CLI via theexecsubcommands. + +## Lifecycle +While using the dev container, try and keep in mind the lifecycle of the container itself. Specifically, containers are ephemeral, meaning they are normally destroyed and recreated whenever the dev environment is rebuilt or updated. Subsequently, a best practice is to avoid storing any persistent data within the container, and instead utilize the project’s source directory, or a separate mounted volume. When altering the development environment inside the container, try to remember to codify your changes into the Dockerfile, or thedevcontainer.jsonconfig file, so that they can be easily reproduced and shared with others. + +## Rebuilding +From time to time, you may need to rebuild the dev container, either because the base image, or.devcontainer/config was updated, or simply out of wanting a new fresh development environment. To do so, simply open the Command Palette (Ctrl+Shift+P) and select theRemote-Containers:RebuildContainercommand. +For example, you may need to rebuild the dev container when: +When necessary, you can also rebuild the container from scratch, e.i. without caching from docker, by selecting theRemote-Containers:RebuildContainerWithoutCachecommand. This instead omits the--cache-fromflag from thedockerbuildxcommand, while also adding the--no-cacheand--pullflags to prevent caching from any existing image layers, using only the latest images from a container registry. +Rebuilding without caching may be necessary when: +Specifically, for this project, volumes remain unaffected by this rebuilding process: i.e. those used to mount the ccache directory or colcon workspace. While volume management is left to the user’s discretion, other projects may of course handle this differently, so be sure to check the./devcontainerconfiguration to inspect how various container resources may be managed. + +Code Examples: + +Language: unknown +File: loginInteractiveShell +``` +find +/tmp +-type +f +-path +"*/devcontainers-*/env-loginInteractiveShell.json" +-exec +\ +jq +-r +'to_entries | .[] | "\(.key)=\(.value | @sh)"' +{} +\; +> +.env + +source +.env + +``` diff --git "a/exported_docs/nav2/Dev Containers\357\203\201.txt" "b/exported_docs/nav2/Dev Containers\357\203\201.txt" new file mode 100644 index 0000000..1ac9cdc --- /dev/null +++ "b/exported_docs/nav2/Dev Containers\357\203\201.txt" @@ -0,0 +1,28 @@ +Title: Dev Containers +URL: https://docs.nav2.org/development_guides/devcontainer_docs/index.html#prerequisites +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## What, Why, How? +Lets briefly explain what dev containers are, why you should use them, and how they work. + +## What is a Dev Container? +A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine’s operating system. + +## Why use a Dev Container? +A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS. + +## How do Dev Containers work? +When you open the project in VS Code, VS Code checks for the dev container configuration nested within the.devcontainerfolder under the project’s root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more. +This is quite similar to earlier tools used to customize and run docker containers for development: + +## Prerequisites +To use dev containers, you’ll need the following: + +## Getting started +Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selectingRemote-Containers:ReopeninContainer. This will create a new container, install any extensions specified in the project’s default.devcontainer/devcontainer.jsonconfig file, and mount the project’s root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing. +While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment. + +## Security +A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent. diff --git "a/exported_docs/nav2/Development Guides\357\203\201.txt" "b/exported_docs/nav2/Development Guides\357\203\201.txt" new file mode 100644 index 0000000..5323582 --- /dev/null +++ "b/exported_docs/nav2/Development Guides\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Development Guides +URL: https://docs.nav2.org/development_guides/index.html +Section: development_guides/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/DistanceController\357\203\201.txt" "b/exported_docs/nav2/DistanceController\357\203\201.txt" new file mode 100644 index 0000000..927b157 --- /dev/null +++ "b/exported_docs/nav2/DistanceController\357\203\201.txt" @@ -0,0 +1,28 @@ +Title: DistanceController +URL: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/DistanceController.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: GoalReached +``` + + + +``` diff --git "a/exported_docs/nav2/DistanceTraveled\357\203\201.txt" "b/exported_docs/nav2/DistanceTraveled\357\203\201.txt" new file mode 100644 index 0000000..68043e1 --- /dev/null +++ "b/exported_docs/nav2/DistanceTraveled\357\203\201.txt" @@ -0,0 +1,45 @@ +Title: DistanceTraveled +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/DistanceTraveled.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +bt_navigator +: +ros__parameters +: +# other bt_navigator parameters +transform_tolerance +: +0.1 +``` + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/DockRobot\357\203\201.txt" "b/exported_docs/nav2/DockRobot\357\203\201.txt" new file mode 100644 index 0000000..3b32576 --- /dev/null +++ "b/exported_docs/nav2/DockRobot\357\203\201.txt" @@ -0,0 +1,27 @@ +Title: DockRobot +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/DockRobot.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: DockRobot +``` + +``` diff --git "a/exported_docs/nav2/Docker for Development: Zero to Hero\357\203\201.txt" "b/exported_docs/nav2/Docker for Development: Zero to Hero\357\203\201.txt" new file mode 100644 index 0000000..30f6516 --- /dev/null +++ "b/exported_docs/nav2/Docker for Development: Zero to Hero\357\203\201.txt" @@ -0,0 +1,754 @@ +Title: Docker for Development: Zero to Hero +URL: https://docs.nav2.org/tutorials/docs/docker_dev.html#nav2-development-image +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial is a hands on walkthrough from your first Docker usage to commands and processes you can use for development of ROS 2 applications using Docker. +This is not an exhaustive introduction by any stretch, but should help you go from nothing to a functional process you can use on a daily basis for development and testing. +If you know some basics about Docker already, you can skip to later sections about development and deployment. +You’ll also find a set of Docker images in the Appendix to this tutorial which are useful for developing with Nav2 or a containerized deployment of it. +The same process template can be used for other company applications and projects as well. +Some other useful resources: + +## Preliminaries +Docker is a tool used to build, deploy, test, and otherwise work with software in an isolated environment, called acontainer. +This diffs from a VM in that it shares the same linux kernel as your host operating system, making it faster to spin up and share host resources. +By building or deploying software in this isolated environment, you can ensure many users, robots, or servers are running the same software with the same software versions across many instances. +It gives you a controlled environment to work in that is reproducible on other developer’s machines and even work in a different (linux-based) operating system than your computer currently runs. +For example, you can run a 22.04 Docker container that contains ROS 2 Humble on Nvidia Jetson’s Jetpack 5.1 (which is a flavor of 20.04) and deploy that container to a fleet of robots. +In common Docker language, animageis the builtDockerfilewhich can be used to createcontainers. +Thus,containersare self-contained, runnable instances of the dockerimage. +TheDockerfileis a set of instructions for how to build an image to create some kind of environment to work in - and often contain applications to deploy in that environment. +The Dockerfile instruct sets have a number of options such as: +Most of these are self explanatory, but you can reference the Docker documentation to learn more and see the full set. +Two special commands worth highlighting areCMDandENTRYPOINTwhich you will see at the bottom of manyDockerfiles. +In the context of ROS Docker containers, you’ll see that these create a bash session and execute aros_entrypoint.shscript. +This script simply sources the ROS environment/opt/ros/.../setup.bashfor your distribution so when you open the container, you’re ready to go. +But these can be used to do more advanced things like run your application or trigger other events. + +## Important Docker Commands +Similarly unexhaustively, it is important to discuss a few docker commandline commands before we move forward. +There are many others, but these are the basic commands which we will use in this walkthrough and likely the most common you’ll use on the day-to-day. +Over the tutorial, build up some important option flags for each, but for now lets talk about the basics: + +## Exploring Your First Container +Lets start this tutorial with getting the latest-and-greatest of ROS 2 Rolling. +Using the OSRF DockerHub server, we can pull down a number of different ROS 2 docker images to work with without having to create a Dockerfile or build them ourselves. +You should then see the following, where the image is being pulled down in multiple layers and finally returning the terminal once complete. +If you then attempt to run this image as a container (the instance of the image): +You should see that it runs for a second then exits the terminal. Yay! It works! But… that’s not very useful, now is it? +OurENTRYPOINTfor the ROS 2 Docker images only sources the ROS 2 installation and so the program returns as completed. +If we want to get into the container to do something useful for ourselves in that environment, we need to open an interactive terminal session with the container. +This is easy to do with the-itflags: +You should now see a terminal session open with a command prompt ofroot@:/#. +This is your docker container. +Take a look around, it should look like any other linux OS. +If you go into/opt/ros/rolling, it should look familiar to you! +If you open a new terminal and runsudodockerps, you should see now one container instance running on your system. +The ID of this container should match the hash in your command prompt. +We mentioned before that the container on spin up will automatically source the ROS installation, so we should be able to immediately play around: +Nice! It all works. Now, if we exit our interactive session (typeexit), we should reenter our computer. +In that second terminal, if you rerunsudodockerps, you should see that the list of containers is now empty since our container is no longer running. +If you want to see a full list of containers, including exited containers, you can use the flag-ato display all containers. +You can see that our container exited successfully. If we now run our docker image again, you should see it back listed without-a. +While we’re here, letslsour container. Oh no! Ournavigator_dockerlayer.txtfile is missing! +That’s completely to be expected. When we exit the container, that instance of the image is destroyed - never again to be seen. +When we run the image again, we’re generating a brand new, clean instance of the image. +Nothing persists. This is an important behavior to understand moving forward. +For development, this is nightmare fuel of losing a day’s work by hitting the wrong button. +For deployment, this is a blessing as you can cleanly restart with no artifacts from a previously failed session and start with a clean slate. +We’ll discuss how to persist data between sessions later on in the tutorial, so fear not! +With our new container still open, lets explore how to work with one container across multiple terminals. If you were to run thedockerruncommand in two terminals, you’d make two separate containers isolated from each other. +Instead, we need to open a new session in the container. Looking at the terminal’s hash orsudodockerpsto find its ID, use theexeccommand to execute the commandbashin the container. +This opens a new interactive session to the container andexec-utes the commandbashto give us a shell to work with (CMDin our Dockerfile does this for us for the spin up terminal). +Since this isn’t a newly spun up container, theENTRYPOINTscript wasn’t run. If you try to run the talker demo again, it won’t find theros2command. +Fear not, simply source your/opt/ros/rolling/setup.bashinstall and you’re good to go. +In either terminal session in the container, if you create a new file, you should be able to see it in the other since this is the same container! +Now we can do something fun while we have both terminals of the same docker container open. Lets run the classic talker/listener demo. In each of the two terminals, run one of these commands. +If you now open a third terminal to your computer and runros2topiclist, you’ll see a notable lack of topics. +What gives? The container is isolated from your host system, so anything happening in the container is currently unavailable to your main computer. +Lets exit our two container terminal instances (exit) and talk about some moredockerrunflags that are useful to know. +This time, we want to expose ROS to our broader system, including our host computer. This time, we’ll use the flag--net=host, this sets the network to look like the host system (i.e. your computer). +In this session, if we run the talkerros2rundemo_nodes_pytalker, now we should be able to subscribe to it from our host computer! +Lets talk about how to keep a container running for longer than than your interactive terminal session. +There are many reasons you want a container to outlive you or run in the background, so that’s what the-dflag is for, or detached. +Lets start off by showing that there are no containers running withsudodockerps. Next start a new container with the flag. +You’ll see the command run for a moment and return.sudodockerpsshould now show a container running. +Copy that container ID and we can nowattachto it: +You should now be in the terminal session. After you do your work, if you want to stop the container, you can exit as we have been in this tutorial (exit) and that will also stop the container. +If you wish to leave the container running, you can use the key sequence Control+P+Q to exit but leave the container running. +In either case, you can show that to yourself usingps. +If you left it running and now wish to stop it externally, you can do so with the following. It may take a few moments to exit. +Finally,dockerimagesis a command used to tell you what docker images you have built or pulled which are available for use. This list will expand over time and is a useful resource to see what you have to work with. + +## Understanding ROS Docker Images +Now that we know a bit about Docker’s basic features and explored the Rolling Desktop Full container, lets look at the Docker images you have to work with in ROS in more detail. +OSRF hosts a DockerHub server containing images of all ROS distributions which you can pull and use. +For each distribution, there are a couple of variants: +These are the same as if you were to useapt install ros-rolling-desktop-full, but in container form. +Each of those containers build off of the previous one usingFROMand then install the binaries described to serve to the container user. +Which you use depends on your application and needs, butosrf/ros:-ros-baseis a good default for development and deployment. +We’re using desktop-full in the context of this tutorial for ease of having rviz2 and such built-in batteries-included. +You can pull and use them the same way as before, for example: +Note that some containers may requireosrf/and others may not. Theosrf/images are released by osrf while the non-prefixed are a part of the official docker libraries. +In general, the desktop installs are withosrf/`and the ros core and base are without. + +## For Docker-Based Development +As mentioned previously, if we create and modify files in the Docker container, these do not persist after the container is exited. +If we want to do some development work that will persist between images, it is wise tomountavolumeto the docker container when we run it. +That is just fancy talk for linking a given set of directories from your host company to the container so that they can be read, modified, and deleted within the container and reflected on the outside. +That way, your work will persist even if you close a container in your local filesystem as if it were developed without the use of a container. +An awesome feature of this is that you can actually build your workspace in one container, destroy that container, and then continue development and rebuild in a new container instance later provided that (1) the same image is used both times and (2) the mounted location within the container is the same each time. +We accomplish this using the-vflag (for volume). There are other options to do this as well, but this is the most straight forward. +It takes in the argument in the form-vwhat/local/dir:/absolute/path/in/container. +If we start a container in our workspace’s root, the following will launch the docker container, sharing the host’s network, and putting your workspace (.) into the container under the directory/my_ws_docker: +If you go to your workspace in another terminal, you should now see that file reflected on your computer! If we run rosdep to install our dependencies in the docker container, we should now be able to build your workspace. +Now, you can make any changes to your code using VSCode or your favorite code editor and have it reflected in the container for building and testing! +This is especially powerful if you’re working with multiple ROS distributions or with a ROS distribution which your host OS doesn’t natively support (such as Humble on Jetpack 5.1 on Nvidia Jetsons). +However, it does get annoying over time to have to wait for all of your dependencies to install manually when you spin up a new container. +Thus, it is useful to build atop one of the provided ROS Docker images to create your own custom development image containing the packages and environment you need to build your application. +That way, you can simply jump into the container and immediately start building. + +## Building a Development Image +Building a new container is easy. The organization instructions of Docker images are outlined inDockerfiles. +Typically, they start with an importFROMto set the starting container to build off of. In our case, a ROS 2 Rolling image. +Then, we run a series ofRUNcommands to perform actions to setup our dependencies so we can have them ready for use when we launch a container. +In theAppendix, you’ll find an example development image that you can use to develop on Nav2. It starts with Rollingros-base, downloads Nav2, and runs rosdep over its packages to install all dependencies. +Once these steps conclude, the image is all setup for any later Nav2 build. +You can build this image usingdockerbuild +Where-tsets the tagged name of the container for later use. +Its important to note that even though your install and build spaces will be reflected in your host workspace, they cannot be run locally when compiled inside of a docker container. +This example development image also upgrades packages which breaks strict version controlling of system andros-baseinstalled packages. +For a deployment situation, you want to ensure you have the same version of all packages – however for ROS 2 Rolling where ABI and API are not promised to be stable due to live development, +it is useful to upgrade so that your source code can build against the latest and greatest. + +## Visualizations from Docker +Some that skip ahead at this point might notice that when launching their applications which involve a GUI (RQT, Rviz2, Gazebo), it crashes and never appears. +Docker’s isolation isn’t just for networking, but also in visualization and other assets. +Thus, we must specifically enable carve outs for GUIs to appear on our screens. +Putting it altogether, you should now be able to open rviz2 inside of the docker container! +At this point, if you have an error remaining, please check docs for the right flags to use. +(Even if you copy+paste around, it shouldn’t take you more than 10 minutes to find a combo that works.) +If you’re on Nvidia Jetson hardware, reference their documentation for the correct set of flags for your Jetpack version. + +## For Docker-Based Deployment +We won’t belabor the details, but Docker is not just for development, but for application deployment as well. +You can run instances of your image on robots, cloud servers, etc as self-containing micro-services or robot application systems. +Typically speaking, you would set yourENTRYPOINTto launch a script which brings up and runs your server(s) for your application. +For example, you could use the deployment image in theAppendixwith anENTRYPOINTto launch your root robot navigation launch filetb3_simulation_gazebo_launch.py, or similar. +You could even have the container launch on bringup usingsystemdin order to have your application automatically launch, containerized, on system startup. + +## Conclusion +At the end of this, you should be able to now: +Its useful to note at this point that the--privilegedflag is a real hammer. If you want to avoid running this, you can find all the individual areas you need to enable for visualization to work. +Also note that--privilegedalso makes it easier to run hardware interfaces like joysticks and sensors by enabling inputs from the host operating system that are processing those inputs. +If in production, you cannot use a hammer, you may need to dig into your system a bit to allow through only the interfaces required for your hardware. +As for potential steps forward: +We hope that’s enough to get you started! +– Your Friendly Neighborhood Navigators + +## Appendix + + +## Nav2 Development Image +This container downloads, but does not install Nav2. +Instead, it pulls the dependencies so that when you run this container, you obtain everything needed to immediately start building and working with Nav2 on any ROS 2 distribution, including Rolling. + +## Nav2 Deployment Image +This image either downloads and installs Nav2 (Rolling; from source) or installs it (from binaries) to have a self contained image of everything you need to run Nav2. +From here, you can go to theGetting Startedto test it out! + +Code Examples: + +Language: unknown +File: dockerimages +``` +sudo +docker +pull +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: dockerimages +``` +steve@reese:~$ +sudo +docker +pull +osrf/ros:rolling-desktop-full +rolling-desktop-full: +Pulling +from +osrf/ros +31bd5f451a84: +Already +exists +d36cae3fb404: +Already +exists +8d68f36a56a7: +Already +exists +299f725c4bf1: +Already +exists +6e16227afc48: +Already +exists +02457a85146c: +Downloading +83 +.7MB/106.5MB +fe0cbdee2808: +Download +complete + +4b4dbddf506a: +Downloading +92 +.86MB/98.14MB +0da90b52c355: +Download +complete + +64de492566b2: +Download +complete + +167d95ac0fce: +Download +complete + +e727072615d0: +Downloading +82 +.61MB/809.8MB +d15e176ed0af: +Waiting + +``` + +Language: unknown +File: dockerimages +``` +sudo +docker +run +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: -it +``` +sudo +docker +run +-it +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: sudodockerps +``` +echo +$ROS_DISTRO +# --> rolling + +ros2 +run +demo_nodes_cpp +talker +# --> [INFO] [1707513434.798456374] [talker]: Publishing: 'Hello World: 1' + +touch +navigator_dockerlayer.txt +l +# <-- you should see this file +``` + +Language: unknown +File: -a +``` +steve@reese:~$ +sudo +docker +ps +-a +CONTAINER +ID +IMAGE +COMMAND +CREATED +STATUS +PORTS +NAMES +7ec0e0b7487f +osrf/ros:rolling-desktop-full +"/ros_entrypoint.sh …" +5 +minutes +ago +Exited +( +0 +) +About +a +minute +ago +strange_tesla +9ccd97ac14f9 +osrf/ros:rolling-desktop-full +"/ros_entrypoint.sh …" +7 +minutes +ago +Exited +( +0 +) +7 +minutes +ago +zen_perlman + +``` + +Language: unknown +File: -a +``` +sudo +docker +run +-it +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: bash +``` +sudo +docker +exec +-it +bce2ad161bf7 +bash +# <-- use your ID +``` + +Language: unknown +File: /opt/ros/rolling/setup.bash +``` +touch +navigator_alligator.txt +ls +# <-- see the new file +# move to the other terminal + +ls +# <-- also see new file +``` + +Language: unknown +File: /opt/ros/rolling/setup.bash +``` +ros2 +run +ros2 +run +demo_nodes_cpp +talker +ros2 +run +demo_nodes_py +listener + +``` + +Language: unknown +File: ros2topiclist +``` +steve@reese:~$ +ros2 +topic +list +/parameter_events +/rosout + +``` + +Language: unknown +File: --net=host +``` +sudo +docker +run +-it +--net += +host +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: ros2rundemo_nodes_pytalker +``` +steve@reese:~$ +ros2 +topic +echo +/chatter +data: +'Hello World: 0' + +--- +data: +'Hello World: 1' + +--- +data: +'Hello World: 2' + +--- + +``` + +Language: unknown +File: sudodockerps +``` +sudo +docker +run +-it +--net += +host +-d +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: attach +``` +sudo +docker +attach +e1d7e035a824 +# <-- use your ID +``` + +Language: unknown +File: ps +``` +sudo +docker +stop +e1d7e035a824 +# <-- use your ID +``` + +Language: unknown +File: dockerimages +``` +steve@reese:~$ +sudo +docker +images +REPOSITORY +TAG +IMAGE +ID +CREATED +SIZE +osrf/ros +rolling-desktop-full +7cd0c5068235 +6 +days +ago +3 +.86GB + +``` + +Language: unknown +File: osrf/ros:-ros-base +``` +sudo +docker +pull +ros:rolling-ros-base +sudo +docker +pull +osrf/ros:humble-desktop + +``` + +Language: unknown +File: /my_ws_docker +``` +sudo +docker +run +-it +--net += +host +-v +.:/my_ws_docker +osrf/ros:rolling-desktop-full + +ls + +cd +my_ws_docker +touch +navigator_activator.txt + +``` + +Language: unknown +File: /my_ws_docker +``` +apt +update +rosdep +init +rosdep +update +rosdep +install +-r +-y +--from-paths +. +--ignore-src +colcon +build + +``` + +Language: unknown +File: dockerbuild +``` +sudo +docker +build +-t +nav2deps:rolling +. + +``` + +Language: unknown +File: --volume="${XAUTHORITY}:/root/.Xauthority" +``` +sudo +docker +run +-it +--net += +host +--privileged +\ +--env += +"DISPLAY= +$DISPLAY +" +\ +--volume += +" +${ +XAUTHORITY +} +:/root/.Xauthority" +\ +osrf/ros:rolling-desktop-full + +``` + +Language: unknown +File: --volume="${XAUTHORITY}:/root/.Xauthority" +``` +rviz2 + +``` + +Language: unknown +File: sudo +``` +ARG +ROS_DISTRO += +rolling +FROM +ros: +${ +ROS_DISTRO +} +-ros-core + +RUN +apt +update +\ +&& +DEBIAN_FRONTEND += +noninteractive +apt +install +-y +--no-install-recommends +--no-install-suggests +\ +ros-dev-tools +\ +wget + +WORKDIR +/root/nav2_ws +RUN +mkdir +-p +~/nav2_ws/src +RUN +git +clone +https://github.com/ros-navigation/navigation2.git +--branch +main +./src/navigation2 +RUN +rosdep +init +RUN +apt +update +&& +apt +upgrade +-y +\ +&& +rosdep +update +\ +&& +rosdep +install +-y +--ignore-src +--from-paths +src +-r + +``` + +Language: unknown +File: sudo +``` +ARG +ROS_DISTRO += +rolling +FROM +ros: +${ +ROS_DISTRO +} +-ros-core + +RUN +apt +update +\ +&& +DEBIAN_FRONTEND += +noninteractive +apt +install +-y +--no-install-recommends +--no-install-suggests +\ +ros-dev-tools +\ +wget + + +# For Rolling or want to build from source a particular branch / fork + +WORKDIR +/root/nav2_ws +RUN +mkdir +-p +~/nav2_ws/src +RUN +git +clone +https://github.com/ros-navigation/navigation2.git +--branch +main +./src/navigation2 +RUN +rosdep +init +RUN +apt +update +&& +apt +upgrade +-y +\ +&& +rosdep +update +\ +&& +rosdep +install +-y +--ignore-src +--from-paths +src +-r +RUN +. +/opt/ros/ +${ +ROS_DISTRO +} +/setup.sh +\ +&& +colcon +build +--symlink-install + + +# For all else, uncomment the above Rolling lines and replace with below +# RUN rosdep init +# RUN apt update && apt upgrade -y \ +# && rosdep update \ +# && apt install \ +# ros-${NAV2_BRANCH}-nav2-bringup \ +# ros-${NAV2_BRANCH}-navigation2 \ +# ros-${NAV2_BRANCH}-turtlebot3-gazebo +``` diff --git "a/exported_docs/nav2/Docking Server\357\203\201.txt" "b/exported_docs/nav2/Docking Server\357\203\201.txt" new file mode 100644 index 0000000..bd943e4 --- /dev/null +++ "b/exported_docs/nav2/Docking Server\357\203\201.txt" @@ -0,0 +1,147 @@ +Title: Docking Server +URL: https://docs.nav2.org/configuration/packages/configuring-docking-server.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +Note:dock_pluginsand eitherdocksordock_databaseare required. + +## SimpleChargingDock Parameters +Simple Charging Dock is a provided charging dock plugin that can handle many docks and common techniques. + +## Example + + +Code Examples: + +Language: unknown +File: isDocked()=true +``` +docking_server +: +ros__parameters +: +controller_frequency +: +50.0 +initial_perception_timeout +: +5.0 +wait_charge_timeout +: +5.0 +dock_approach_timeout +: +30.0 +undock_linear_tolerance +: +0.05 +undock_angular_tolerance +: +0.1 +max_retries +: +3 +base_frame +: +"base_link" +fixed_frame +: +"odom" +dock_backwards +: +false +dock_prestaging_tolerance +: +0.5 +# Types of docks +dock_plugins +: +[ +'nova_carter_dock' +] +nova_carter_dock +: +plugin +: +'opennav_docking::SimpleChargingDock' +# Also 'opennav_docking::SimpleNonChargingDock' +docking_threshold +: +0.05 +staging_x_offset +: +-0.7 +use_external_detection_pose +: +true +use_battery_status +: +false +# true +use_stall_detection +: +false +external_detection_timeout +: +1.0 +external_detection_translation_x +: +-0.18 +external_detection_translation_y +: +0.0 +external_detection_rotation_roll +: +-1.57 +external_detection_rotation_pitch +: +-1.57 +external_detection_rotation_yaw +: +0.0 +filter_coef +: +0.1 +# Dock instances +docks +: +[ +'home_dock' +] +home_dock +: +type +: +'nova_carter_dock' +frame +: +map +pose +: +[ +0.0 +, +0.0 +, +0.0 +] +id +: +'c67f50cb-e152-4720-85cc-5eb20bd85ce8' +controller +: +k_phi +: +3.0 +k_delta +: +2.0 +v_linear_min +: +0.15 +v_linear_max +: +0.15 +``` diff --git "a/exported_docs/nav2/DriveOnHeading\357\203\201.txt" "b/exported_docs/nav2/DriveOnHeading\357\203\201.txt" new file mode 100644 index 0000000..863bc69 --- /dev/null +++ "b/exported_docs/nav2/DriveOnHeading\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: DriveOnHeading +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/DriveOnHeading.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: DriveOnHeading +``` + +``` diff --git "a/exported_docs/nav2/Dynamic Object Following\357\203\201.txt" "b/exported_docs/nav2/Dynamic Object Following\357\203\201.txt" new file mode 100644 index 0000000..a3ebae9 --- /dev/null +++ "b/exported_docs/nav2/Dynamic Object Following\357\203\201.txt" @@ -0,0 +1,224 @@ +Title: Dynamic Object Following +URL: https://docs.nav2.org/tutorials/docs/navigation2_dynamic_point_following.html#run-dynamic-object-following-in-nav2-simulation +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to use Nav2 for a different task other than going from point A to point B. In this case, we will use Nav2 to follow a moving object at a distance indefinitely. +This task is useful in cases such as following a person or another robot. Below are some sample videos of applications that could be created using this capability. The “Carry My Luggage” RoboCup @ Home test, in which theCATIE Roboticsteam performs the test successfully and this real (future) world application: +The requirements for this task are as follows: +The detection of the dynamic object (like a person) to follow is outside the scope of this tutorial. As shown in the following diagram, your application should provide a detector for the object(s) of interest, +send the initial pose to theNavigateToPoseaction, and update it on a topic for the duration of the task. Many different types of detectors exist that you can leverage for this application: + +## Tutorial Steps + + +## 0- Create the Behavior Tree +Let’s start from this simple behavior tree. This behavior tree replans a new path at 1 hz and passes that path to the controller to follow: +First, let’s make this behavior run until there’s a failure. For this purpose, we will use theKeepRunningUntilFailurecontrol node. +We will then use the decoratorGoalUpdaterto accept updates of the dynamic object pose we’re trying to follow. This node takes as input the current goal and subscribes to the topic/goal_update. It sets the new goal asupdated_goalif a new goal on that topic is received. +To stay at a certain distance from the target, we will use the action nodeTruncatePath. This node modifies a path making it shorter so we don’t try to navigate into the object of interest. We can set up the desired distance to the goal using the input portdistance. +Now, you may save this behavior tree and use it in our navigation task. +For reference, this exact behavior tree ismade availableto you batteries included in thenav2_bt_navigatorpackage. + +## 1- Setup Rviz clicked point +We are going to use RViz instead of a full application so you can test at home without finding a detector to get started. We will use the “clicked point” button on the toolbar to substitute object detections to provide goal updates to Nav2. This button allows you to +publish coordinates in the topic/clicked_point. This point needs to be sent to the behavior tree, using the programclicked_point_to_pose, fromthis repo. Clone +this repo in your workspace, build, and type in a terminal. +ros2runnav2_test_utilsclicked_point_to_pose +Optionally, you can remap this topic in your rviz configuration file togoal_updates. + +## 2- Run Dynamic Object Following in Nav2 Simulation +Start Nav2 in one terminal: +ros2launchnav2_bringuptb3_simulation_launch.pydefault_bt_xml_filename:=/path/to/bt.xml +Open RViz and, after initialize the robot position, command the robot to navigate to any position. Use the button clicked point to simulate a new detection of the object of interest, as shown in the video in the head of this tutorial. +When you have a detector detecting your obstacle at a higher rate (1 hz, 10 hz, 100 hz) you will see a far more reactive robot following your detected object of interest! + +Code Examples: + +Language: unknown +File: NavigateToPose +``` + + + + + + + + + + +``` + +Language: unknown +File: KeepRunningUntilFailure +``` + + + + + + + + + + + + +``` + +Language: unknown +File: updated_goal +``` + + + + + + + + + + + + + + +``` + +Language: unknown +File: distance +``` + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Eloquent to Foxy\357\203\201.txt" "b/exported_docs/nav2/Eloquent to Foxy\357\203\201.txt" new file mode 100644 index 0000000..3e05d81 --- /dev/null +++ "b/exported_docs/nav2/Eloquent to Foxy\357\203\201.txt" @@ -0,0 +1,103 @@ +Title: Eloquent to Foxy +URL: https://docs.nav2.org/migration/Eloquent.html#eloquent-migration +Section: concepts/index.html +-------------------------------------------------------------------------------- + + +## General +The lifecycle manager was split into 2 unique lifecycle managers. +They are thenavigation_lifecycle_managerandlocalization_lifecycle_manager. +This gives each process their own manager to allow users to switch between SLAM and localization without effecting Navigation. +It also reduces the redundant code innav2_bringup. +The lifecycle manager also now containsBondconnections to each lifecycle server. +This means that if a server crashes or exits, the lifecycle manager will be constantly checking and transition down its lifecycle nodes for safety. +This acts as a watchdog during run-time to complement the lifecycle manager’s transitioning up and down from active states. Seethis PR for details. +A fix to the BT navigator was added to remove a rare issue where it may crash due to asynchronous issues. +As a result, a behavior tree is created for each navigation request rather than resetting an existing tree. +The creation of this tree will add a small amount of latency. +Proposals to reduce this latency will be considered before the next release. + +## Server Updates +All plugin servers (controller, planner, recovery) now supports the use of multiple plugins. +This can be done by loading a map of plugins, mapping the name of the plugin to its intended use-case. +Each server defines a parameter where the list of names for the plugins to be loaded can be defined. +The type of plugin to be mapped to a particular name has to be defined using thepluginparameter in the plugin namespace for each name defined in the server plugin list. +Each name in the plugin parameter list is expected to have thepluginparameter defined. +An example:controller_serverdefines the parametercontroller_pluginswhere a list of plugin names can be defined: +FollowPathcontroller is of typedwb_local_planner/DWBLocalPlannerandDynamicFollowPathof typeteb_local_planner/TEBLocalPlanner. +Each plugin will load the parameters in their namespace, e.g.FollowPath.max_vel_x, rather than globally in the server namespace. +This will allow multiple plugins of the same type with different parameters and reduce conflicting parameter names. +DWB Contains new parameters as an update relative to the ROS 1 updates,see here for more information. +Additionally, the controller and planner interfaces were updated to include astd::stringnameparameter on initialization. +This was added to the interfaces to allow the plugins to know the namespace it should load its parameters in. +E.g. for a controller to find the parameterFollowPath.max_vel_x, it must be given its name,FollowPathto get this parameter. +All plugins will be expected to look up parameters in the namespace of its given name. + +## New Plugins +Many new behavior tree nodes were added. +These behavior tree nodes are now BT plugins and dynamically loadable at run-time using behavior tree cpp v3. +The default behavior trees have been upgraded to stop the recovery behaviours and trigger a replanning when the navigation goal is preempted. +Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions. +These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins. +Original GitHub tickets: + +## Map Server Re-Work +map_saverwas re-worked and divided into 2 parts: CLI and server. +CLI part is a command-line tool that listens incoming map topic, saves map once into a file and finishes its work. This part is remained to be almost untouched: CLI executable was renamed frommap_savertomap_saver_cliwithout changing its functionality. +Server is a new part. It spins in the background and can be used to save map continuously through asave_mapservice. By each service request it tries to listen incoming map topic, receive a message from it and write obtained map into a file. +map_serverwas dramatically simplified and cleaned-up.OccGridLoaderwas merged withMapServerclass as it is intended to work only with oneOccupancyGridtype of messages in foreseeable future. +Map Server now has newmap_iodynamic library. All functions saving/loadingOccupancyGridmessages were moved frommap_serverandmap_saverhere. These functions could be easily called from any part of external ROS 2 code even if Map Server node was not started. +map_loaderwas completely removed fromnav2_util. All its functionality already present inmap_io. Please use it in your code instead. +Please refer to theoriginal GitHub ticketandMap Server READMEfor more information. + +## New Particle Filter Messages +New particle filter messages for particle clouds were added to include the particle weights along with their poses.nav2_msgs/Particledefines a single particle with a pose and a weight in a particle cloud.nav2_msgs/ParticleClouddefines a set of particles, each with a pose and a weight. +AMCLnow publishes its particle cloud as anav2_msgs/ParticleCloudinstead of ageometry_msgs/PoseArray. +See here for more information. + +## Selection of Behavior Tree in each navigation action +TheNavigateToPoseaction allows now to select in the action request the behavior tree to be used bybt_navigatorfor carrying out the navigation action through thestringbehavior_treefield. This field indicates the absolute path of the xml file that will be used to use to carry out the action. If no file is specified, leaving this field empty, the default behavior tree specified in thedefault_bt_xml_filenameparameterwill be used. +This functionality has been discussed inthe ticket #1780, and carried out inthe pull request #1784. + +## FollowPoint Capability +A new behavior treefollowpoint.xmlhas added. This behavior tree makes a robot follow a dynamically generated point, keeping a certain distance from the target. This can be used for moving target following maneuvers. +This functionality has been discussed inthe ticket #1660, and carried out inthe pull request #1859. + +## New Costmap Layer +The range sensor costmap has not been ported to navigation2 asnav2_costmap_2d::RangeSensorLayer". It uses the same +probabilistic model as theROS1layer as well as much of the +same interface. Documentation on parameters has been added to docs/parameters and the docs.nav2.org underConfigurationGuide. + +Code Examples: + +Language: unknown +File: controller_plugins +``` +controller_server +: +ros__parameters +: +controller_plugins +: +[ +"FollowPath" +, +"DynamicFollowPath" +] +FollowPath +: +plugin +: +"dwb_core/DWBLocalPlanner" +max_vel_x +: +0.26 +DynamicFollowPath +: +plugin +: +"teb_local_planner/TEBLocalPlanner" +max_vel_x +: +0.5 +``` diff --git "a/exported_docs/nav2/Filtering of Noise-Induced Obstacles\357\203\201.txt" "b/exported_docs/nav2/Filtering of Noise-Induced Obstacles\357\203\201.txt" new file mode 100644 index 0000000..a9a74be --- /dev/null +++ "b/exported_docs/nav2/Filtering of Noise-Induced Obstacles\357\203\201.txt" @@ -0,0 +1,91 @@ +Title: Filtering of Noise-Induced Obstacles +URL: https://docs.nav2.org/tutorials/docs/filtering_of_noise-induced_obstacles.html#tutorial-steps +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +Noisy sensor measurements can cause to errors inVoxelLayerorObstacleLayer. As a result, salt and pepper noise may appear on the costmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. While the images above show both salt and pepper noise as well as error due to mislocalization, this layer will only remove sensor noise, not mislocalized artifacts misaligned with the static map. +This tutorial shows how to configure filtering of false obstacles caused by noise. This functionality is provided by theDenoiseLayercostmap layer plugin which will be enabled and used in this document. + +## Requirements +It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install. + +## Tutorial Steps + + +## 1. Enable Denoise Layer +Denoise Layer is Costmap2D plugin. You can enable theDenoiseLayerplugin in Costmap2D by addingdenoise_layerto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapand (or)local_costmapto filter noise on a global or local map. The DenoiseLayer plugin should have the following parameter defined: +Full list of parameters supported byDenoiseLayerare listed atDenoise Layer Parameterspage. +It is important to note thatDenoiseLayertypically should be placed before the inflation layer. +This is required to prevent inflation from noise-induced obstacles. +Moreover,DenoiseLayerprocesses only obstacle information in the costmap. +ValuesINSCRIBED_INFLATED_OBSTACLE,LETHAL_OBSTACLEand optionallyNO_INFORMATIONwill be interpreted as obstacle cell. Cells with any other values will be interpreted asFREE_SPACEwhen processed (won’t be distorted in the cost map). +If a cell with an obstacle is recognized as noise, it will be replaced byFREE_SPACEafter processing. +To enableDenoiseLayerfor both global and local costmaps, use the following configuration: + +## 2. Run Nav2 stack +After Denoise Layer was enabled for global/local costmaps, run Nav2 stack as written inGetting Started: +And check that filter is working properly: with the default parameters, +no standalone obstacles should remain on the cost map. This can be checked, for example, in RViz main window displaying local and global costmaps after removing unnecessary particles (illustrated at the top of this tutorial). + +## How it works +The plugin is based on two algorithms. +When parameterminimal_group_size= 2, the first algorithm turns on. +It applyerosionfunction with kernel from image below (left ifgroup_connectivity_type= 4 or right ifgroup_connectivity_type= 8) to the costmap. +White color of the kernel pixel means to use the value, black means to ignore it. +As a result of erosion function the neighbors image is created. Each possible position of the kernel on the costmap corresponds to one pixel of the neighbors image. The pixel value of this image is equal to the maximum of 4/8 costmap pixels corresponding to the white pixels of the mask. +In other words, the pixel of the neighbors image is equal to the obstacle code if there is an obstacle nearby, the free space code in other case. +After that, obstacles corresponding to free space code on neighbors image are removed. +This process is illustrated below. On the left side of the image is a costmap, on the right is a neighbors image. White pixels are free space, black pixels are obstacles,group_connectivity_type= 4. +Obstacles marked at the end of the animation will be removed. +When parameterminimal_group_size> 2, the second algorithm is executed. +This is a generalized solution that allows you to remove groups of adjacent obstacles if their total number is less thanminimal_group_size. +To select groups of adjacent obstacles, the algorithm performs their segmentation. +The type of cell connectivity in one segment is determined by the parametergroup_connectivity_type. +Next, the size of each segment is calculated. +Obstacles segments with size less than theminimal_group_sizeare replaced with empty cells. +This algorithm is about 10 times slower than first, so use it with caution and only when necessary. +Its execution time depends on the size of the processed map fragment (and not depend on the value ofminimal_group_size). +This algorithm is illustrated in the animation below (group_connectivity_type= 8). +Obstacles marked at the end of the animation will be removed (groups that size less 3). + +Code Examples: + +Language: unknown +File: DenoiseLayer +``` +global_costmap: + global_costmap: + ros__parameters: + ... + plugins: ["static_layer", "obstacle_layer", "denoise_layer", "inflation_layer"] + ... + denoise_layer: + plugin: "nav2_costmap_2d::DenoiseLayer" + enabled: True +... +local_costmap: + local_costmap: + ros__parameters: + ... + plugins: ["voxel_layer", "denoise_layer", inflation_layer"] + ... + keepout_filter: + plugin: "nav2_costmap_2d::DenoiseLayer" + enabled: True + +``` + +Language: unknown +File: DenoiseLayer +``` +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +headless: += +False + +``` diff --git "a/exported_docs/nav2/First-Time Robot Setup Guide\357\203\201.txt" "b/exported_docs/nav2/First-Time Robot Setup Guide\357\203\201.txt" new file mode 100644 index 0000000..83f4761 --- /dev/null +++ "b/exported_docs/nav2/First-Time Robot Setup Guide\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: First-Time Robot Setup Guide +URL: https://docs.nav2.org/setup_guides/index.html#setup-guides +Section: tuning/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/Follow Dynamic Point\357\203\201.txt" "b/exported_docs/nav2/Follow Dynamic Point\357\203\201.txt" new file mode 100644 index 0000000..8f4d480 --- /dev/null +++ "b/exported_docs/nav2/Follow Dynamic Point\357\203\201.txt" @@ -0,0 +1,85 @@ +Title: Follow Dynamic Point +URL: https://docs.nav2.org/behavior_trees/trees/follow_point.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: KeepRunningUntilFailure +``` + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/FollowPath\357\203\201.txt" "b/exported_docs/nav2/FollowPath\357\203\201.txt" new file mode 100644 index 0000000..6de7867 --- /dev/null +++ "b/exported_docs/nav2/FollowPath\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: FollowPath +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/FollowPath.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: FollowPath +``` + +``` diff --git "a/exported_docs/nav2/Foxy to Galactic\357\203\201.txt" "b/exported_docs/nav2/Foxy to Galactic\357\203\201.txt" new file mode 100644 index 0000000..36f62c3 --- /dev/null +++ "b/exported_docs/nav2/Foxy to Galactic\357\203\201.txt" @@ -0,0 +1,213 @@ +Title: Foxy to Galactic +URL: https://docs.nav2.org/migration/Foxy.html#removed-bt-xml-launch-configurations +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## NavigateToPose Action Feedback updates +The NavigateToPose action feedback has two improvements: + +## NavigateToPose BT-node Interface Changes +The NavigateToPose input port has been changed to PoseStamped instead of Point and Quaternion. +SeeNavigateToPosefor more information. + +## NavigateThroughPoses and ComputePathThroughPoses Actions Added +TheNavigateThroughPosesaction has been added analog to theNavigateToPose. Rather than going to a single position, this Action will allow a user to specify a number of hard intermediary pose constraints between the start and final pose to plan through. The newComputePathThroughPosesaction has been added to theplanner_serverto process these requests throughNgoal_poses. +TheComputePathThroughPosesaction server will take in a set ofNgoals to achieve, plan through each pose and concatenate the output path for use in navigation. The controller and navigator know nothing about the semantics of the generated path, so the robot will not stop or slow on approach to these goals. It will rather continue through each pose as it were any other point on the path continuously. When paired with theSmacPlanner, this feature can be used to generatecompletely kinematically feasible trajectories through pose constraints. +If you wish to stop at each goal pose, consider using the waypoint follower instead, which will stop and allow a user to optionally execute a task plugin at each pose. + +## ComputePathToPose BT-node Interface Changes +Thestartinput port has been added to optionally allow the request of a path fromstarttogoalinstead of from the current position of the robot togoal. +SeeComputePathToPosefor more information. + +## ComputePathToPose Action Interface Changes +These two additional fields have been added to optionally allow, whenuse_startis true, the request of a path fromstarttogoalinstead of from the current position of the robot togoal. Corresponding changes have been done of the Planner Server. + +## BackUp BT-node Interface Changes +Thebackup_distandbackup_speedinput ports should both be positive values indicating the distance to go backward respectively the speed with which the robot drives backward. + +## BackUp Recovery Interface Changes +speedin a backup recovery goal should be positive indicating the speed with which to drive backward.target.xin a backup recovery goal should be positive indicating the distance to drive backward. +In both cases negative values are silently inverted. + +## Nav2 Controllers and Goal Checker Plugin Interface Changes +As ofthis PR 2247, thecontrollerplugins will now be given a pointer to the current goal checker in use of the navigation task incomputeAndPublishVelocity(). This is geared to enabling controllers to have access to predictive checks for goal completion as well as access to the state information of the goal checker plugin. +Thegoal_checkerplugins also have the change of including agetTolerances()method. This method allows a goal checker holder to access the tolerance information of the goal checker to consider at the goal. Each field of theposeandvelocityrepresents the maximum allowable error in each dimension for a goal to be considered completed. In the case of a translational tolerance (combined X and Y components), each the X and Y will be populated with the tolerance value because it is themaximumtolerance in the dimension (assuming the other has no error). If the goal checker does not contain any tolerances for a dimension, thenumeric_limitslowest()value is utilized in its place. + +## FollowPath goal_checker_id attribute +For example: you could use for some specific navigation motion a more precise goal checker than the default one that it is used in usual motions. +Below it is shown an example of goal_checker configuration of the controller_server node. + +## Groot Support +Live Monitoring and Editing of behavior trees with Groot is now possible. +Switching bt-xmls on the fly through a new goal request is also included. +This is all done without breaking any APIs. +Enabled by default. + +## New Plugins +nav2_waypoint_followerhas an action server that takes in a list of waypoints to follow and follow them in order. In some cases we might want robot to +perform some tasks/behaviours at arrivals of these waypoints. In order to perform such tasks, a generic plugin interfaceWaypointTaskExecutorhas been added tonav2_core. +Users can inherit from this interface to implement their own plugin to perform more specific tasks at waypoint arrivals for their needs. +Several example implementations are included innav2_waypoint_follower.WaitAtWaypointandPhotoAtWaypointplusings are included innav2_waypoint_followeras run-time loadable plugins.WaitAtWaypointsimply lets robot to pause for a specified amount of time in milliseconds, at waypoint arrivals. +WhilePhotoAtWaypointtakes photos at waypoint arrivals and saves the taken photos to specified directory, the format for taken photos also can be configured through parameters. +All major image formats such aspng,jpeg,jpgetc. are supported, the default format ispng. +Loading a plugin of this type is done throughnav2_bringup/params/nav2_param.yaml, by specifying plugin’s name, type and it’s used parameters. +Original GitHub tickets: + +## Costmap Filters +A new concept interacting with spatial-dependent objects called “Costmap Filters” appeared in Galactic (more information about this concept could be found atNavigation Conceptspage). Costmap filters are acting as a costmap plugins, applied to a separate costmap above common plugins. In order to make a filtered costmap and change robot’s behavior in annotated areas, filter plugin reads the data came from filter mask. Then this data is being linearly transformed into feature map in a filter space. It could be passability of an area, maximum speed limit in m/s, robot desired direction in degrees or anything else. Transformed feature map along with the map/costmap, sensors data and current robot position is used in plugin’s algorithms to make required updates in the resulting costmap and robot’s behavior. +Architecturally, costmap filters consists fromCostmapFilterclass which is a basic class incorporating much common of its inherited filter plugins: +Each costmap filter subscribes to filter info topic (publishing byCostmap Filter Info Publisher Server) having all necessary information for loaded costmap filter and filter mask topic.SpeedFilteradditionally publishes maximum speed restrictingmessagestargeted for a Controller to enforce robot won’t exceed given limit. +High-level design of this concept could be foundhere. The functionality of costmap filters is being discussed inthe ticket #1263and carried out byPR #1882. The following tutorials:Navigating with Keepout ZonesandNavigating with Speed Limitswill help to easily get involved withKeepoutFilterandSpeedFilterfunctionalities. + +## SmacPlanner +A new package,nav2_smac_plannerwas added containing 4 or 8 connected 2D A*, and Dubin and Reed-shepp model hybrid-A* with smoothing, multi-resolution query, and more. +Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. We support differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support cars, car-like, and ackermann vehicles using theSmacPlannerplugin which implements a Hybrid-A* planner. This plugin is also useful for curvature constrained planning, like when planning robot at high speeds to make sure they don’t flip over or otherwise skid out of control. +TheSmacPlannerfully-implements the Hybrid-A* planner as proposed inPractical Search Techniques in Path Planning for Autonomous Driving, including hybrid searching, CG smoothing, analytic expansions and heuristic functions. + +## ThetaStarPlanner +A new package,nav2_theta_star_plannerwas added containing 4 or 8 connected Theta* implementation for 2D maps. +This package implements an optimized version of the Theta* Path Planner (specifically theLazy Theta* Pvariant) to plan any-angled paths for differential-drive and omni-directional robots, while also taking into account the costmap costs. This plugin is useful for the cases where you might want to plan a path at a higher rate but without requiring extremely smooth paths around the corners which, for example, could be handled by a local planner/controller. + +## RegulatedPurePursuitController +A new package,nav2_regulated_pure_pursuit_controllerwas added containing a novel variant of the Pure Pursuit algorithm. +It also includes configurations to enable Pure Pursuit and Adaptive Pure Pursuit variations as well. +This variation is specifically targeting service / industrial robot needs. +It regulates the linear velocities by curvature of the path to help reduce overshoot at high speeds around blind corners allowing operations to be much more safe. +It also better follows paths than any other variation currently available of Pure Pursuit. +It also has heuristics to slow in proximity to other obstacles so that you can slow the robot automatically when nearby potential collisions. +It also implements the Adaptive lookahead point features to be scaled by velocities to enable more stable behavior in a larger range of translational speeds. +There’s more this does, that that’s the general information. See the package’sREADMEfor more. + +## Costmap2Dcurrent_Usage +In costmap2D,current_was used in ROS1 to represent whether a costmap layer was still enabled and actively processing data. It would be turned tofalseonly under the situation that the expected update rate of a sensor was not met, so it was getting stale or no messages. It acts as a fail-safe for if a navigation sensor stops publishing. +In galactic, that will remain turn, however it will also add additional capabilities. It is also now set tofalsewhen a costmap is reset due to clearing or other navigation recoveries. That stops the robot from creating a plan or control effort until after the costmap has been updated at least once after a reset. This enables us to make sure we cannot ever create a path or control with a completely empty costmap, potentially leading to collisions, due to clearing the costmap and then immediately requesting an algorithm to run. + +## Standard time units in parameters +To follow the SI units outlined in REP-103 to the “T” nodes below were modified to use seconds consistently in every parameter. Under each node name you can see which parameters changed to seconds instead of using milliseconds. + +## Ray Tracing Parameters +Raytracing functionality was modified to include a minimum range parameter from which ray tracing starts to clear obstacles to avoid incorrectly clearing obstacles too close to the robot. This issue was mentioned inROS Answers. An existing parameterraytrace_rangewas renamed toraytrace_max_rangeto reflect the functionality it affects. The renamed parameters and the plugins that they belong to are mentioned below. The changes were introduced in thispull request. + +## Obstacle Marking Parameters +Obstacle marking was modified to include a minimum range parameter from which obstacles are marked on the costmap to prevent addition of obstacles in the costmap due to noisy and incorrect measurements. This modification is related to the change with the raytracing parameters. The renamed parameters, newly added parameters and the plugins they belong to are given below. + +## Recovery Action Changes +The recovery actions,SpinandBackUpwere modified to correctly returnFAILUREif the recovery action is aborted due to a potential collision. Previously, these actions incorrectly always returnedSUCCESS. Changes to this resulted in downstream action clients, such as the default behavior tree. The changes were introduced in thispull request 1855. + +## Default Behavior Tree Changes +The default behavior tree (BT)navigate_w_replanning_and_recovery.xmlhas been updated to allow for replanning in between recoveries. The changes were introduced in thisPR 1855. Additionally, an alternative BTnavigate_w_replanning_and_round_robin_recovery.xmlwas removed due to similarity with the updated default BT. + +## NavFn Planner Parameters +The NavFn Planner has now its 3 parameters reconfigurable at runtime (tolerance,use_astarandallow_unknown). The changes were introduced in thispull request 2181. + +## New ClearCostmapExceptRegion and ClearCostmapAroundRobot BT-nodes +The ClearEntireCostmap action node was already implemented but the ClearCostmapExceptRegion and ClearCostmapAroundRobot BT nodes calling the sister services(local_or_global)_costmap/clear_except_(local_or_global)_costmapandclear_around_(local_or_global)_costmapof Costmap 2D were missing, they are now implemented in a similar way. They both expose areset_distanceinput port. SeeClearCostmapExceptRegionandClearCostmapAroundRobotfor more. The changes were introduced in thispull request 2204. + +## New Behavior Tree Nodes +A new behavior tree node was added and dynamically loadable at run-time using behavior tree cpp v3. +Seenav2_behavior_treefor a full listing, orNavigation Pluginsfor the current list of behavior tree plugins and their descriptions. +These plugins are set as default in thenav2_bt_navigatorbut may be overridden by thebt_pluginsparameter to include your specific plugins. +Original GitHub tickets: +Additionally, behavior tree nodes were modified to contain their own local executors to spin for actions, topics, services, etc to ensure that each behavior tree node is independent of each other (e.g. spinning in one BT node doesn’t trigger a callback in another). + +## sensor_msgs/PointCloud to sensor_msgs/PointCloud2 Change +Due to deprecation ofsensor_msgs/PointCloudthe topics which were publishing sensor_msgs/PointCloud are converted to sensor_msgs/PointCloud2. The details on these topics and their respective information are listed below. +These changes were introduced inpull request 2263. + +## ControllerServer New Parameter failure_tolerance +A new parameterfailure_tolerancewas added to the Controller Server for tolerating controller plugin exceptions without failing immediately. It is analogous tocontroller_patiencein ROS(1) Nav. SeeController Serverfor description. +This change was introduced in thispull request 2264. + +## Removed BT XML Launch Configurations +The launch python configurations for CLI setting of the behavior tree XML file has been removed. Instead, you should use the yaml files to set this value. If you, however, have apathto the yaml file that is inconsistent in a larger deployment, you can use theRewrittenYamltool in your parent launch file to remap the default XML paths utilizing theget_shared_package_path()directory finder (or as you were before in python3). +The use of map subscription QoS launch configuration was also removed, use parameter file. +This change was introduced in thispull request 2295. + +## Nav2 RViz Panel Action Feedback Information +The Nav2 RViz Panel now displays the action feedback published bynav2_msgs/NavigateToPoseandnav2_msgs/NavigateThroughPosesactions. +Users can find information like the estimated time of arrival, distance remaining to goal, time elapsed since navigation started, and number of recoveries performed during a navigation action directly through the RViz panel. +This feature was introduced in thispull request 2338. + +Code Examples: + +Language: unknown +File: numeric_limitslowest() +``` + +``` + +Language: unknown +File: GridBased +``` +controller_server +: +ros__parameters +: +goal_checker_plugins +: +[ +"general_goal_checker" +, +"precise_goal_checker" +] +precise_goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +general_goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +``` + +Language: unknown +File: nav2_bringup/params/nav2_param.yaml +``` +waypoint_follower +: +ros__parameters +: +loop_rate +: +20 +stop_on_failure +: +false +waypoint_task_executor_plugin +: +"wait_at_waypoint" +wait_at_waypoint +: +plugin +: +"nav2_waypoint_follower::WaitAtWaypoint" +enabled +: +True +waypoint_pause_duration +: +0 +``` diff --git "a/exported_docs/nav2/Galactic to Humble\357\203\201.txt" "b/exported_docs/nav2/Galactic to Humble\357\203\201.txt" new file mode 100644 index 0000000..d273c92 --- /dev/null +++ "b/exported_docs/nav2/Galactic to Humble\357\203\201.txt" @@ -0,0 +1,299 @@ +Title: Galactic to Humble +URL: https://docs.nav2.org/migration/Galactic.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Major improvements to Smac Planners +The Smac Planner was significantly improved, of both the 2D and Hybrid-A* implementations, making the paths better, faster, and of higher quality. +Additional improvements were made to include aanalytic_expansion_max_lengthparameter such that analytic expansions are limited in their potential length. If the length is too far, reject this expansion. This prevents unsafe shortcutting of paths into higher cost areas far out from the goal itself, let search to the work of getting close before the analytic expansion brings it home. This should never be smaller than 4-5x the minimum turning radius being used, or planning times will begin to spike. +Further, the traversal cost and heuristic cost computations were updatedrequiring retuning of your penalty functionsif you have a previously existing configuration. Defaults of the algorithm were also retuned appropriately to the change for similar our of the box behavior as before (to use as a reference). + +## Simple (Python) Commander +This PR 2411introduces a new package to Nav2, called thenav2_simple_commander. It is a set of functions in an object,BasicNavigator, which can be used to build Nav2-powered autonomy tasks in Python3 without concerning yourself with the Nav2, ROS 2, or Action server details. It contains a simple API taking common types (primarilyPoseStamped) and handles all of the implementation details behind the hood. For example, this is a simple navigation task using this API: +The full API can be found in the README of the package. A number of well commented examples and demos can also be found in the package’s source code at the link prior. + +## Reduce Nodes and Executors +In order for nav2 to make the best use of ROS 2, we need minimize the number of nodes and executors in nav2, which can improve performance. +This functionality has been discussed inthe ticket #816, and carried out in + +## API Change for nav2_core +PR 2976changes the API fornav2_core::Controllerandnav2_core::Smootherby replacing the use of shared pointer references(constshared_ptr<>&)to shared pointers(shared_ptr<>). +Use of shared pointer references meant that the shared pointer counter was never incremented. + +## Extending the BtServiceNode to process Service-Results +This PR 2481andPR 2992addressthe ticketandthis ticketand adds a virtualon_completion()function to theBtServiceNodeclass (can be found here). +Similar to the already existing virtualon_wait_for_result()function, it can be overwritten in the child class to react to a respective event with some user-defined operation. +The addedon_completion()function will be called after the service interaction of theBtServiceNodehas been successfully completed. +The returnedBT::NodeStatuswill set the current status of the BT-Node. Since the function has access to the results of the service, the returned node-status can depend on those service results, for example. +The normal behavior of theBtServiceNodeis not affected by introducing theon_completion()function, since the the default implementation still simply returnsBT::NodeStatus::SUCCESS, if the service interaction completed successfully. + +## Including new Rotation Shim Controller Plugin +This PR 2718introduces the newnav2_rotation_shim_controller. This controller will check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto the primary controller to execute. If it is outside of the threshold, this controller will rotate the robot towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot is still going to be rotating, allowing the current plugin to take control for a smooth hand off into path tracking. +The Rotation Shim Controller is suitable for: + +## Spawning the robot in Gazebo +This PR 2473deletes the pkgnav2_gazebo_spawnerinside nav2_bringup directory. Instead ofnav2_gazebo_spawnerthe Nodespawn_entity.pyofgazebo_rosis recommended to spawn the robot in gazebo. +Note that + +## Recovery Behavior Timeout +Recoveries in Nav2, spin and backup, now havetime_allowanceports in their BT nodes and request fields in their actions to specify a timeout. This helps ensure that the robot can exit a backup or spin primitive behavior in case it gets stuck or otherwise is unable to backup the full distance over a reasonable block of time. + +## New parameteruse_final_approach_orientationfor the 3 2D planners +Pull request 2488adds a new parameteruse_final_approach_orientationto the 3 2D planners (Theta*, SmacPlanner2D and NavFn),falseby default. Iftrue, the last pose of the path generated by the planner will have its orientation set to the approach orientation, i.e. the orientation of the vector connecting the last two points of the path. It allows sending the robot to a position (x,y) instead of a pose (x,y,theta) by effectively ignoring the goal orientation. +For example, below, for the same goal with an orientaton pointed left of the screen,use_final_approach_orientation=false(left) anduse_final_approach_orientation=true(right) + +## SmacPlanner2D and Theta*: fix goal orientation being ignored +This pull request 2488fixesthe issueof the goal pose orientation being ignored (the end path pose orientation was always set to 0). + +## SmacPlanner2D, NavFn and Theta*: fix small path corner cases +This PR 2488ensures the planners are not failing when the distance between the start and the goal is small (i.e. when they are on the same costmap cell), and in that case the output path is constructed with a single pose. + +## Change and fix behavior of dynamic parameter change detection +Thisandthis PRmodify the method used to catch the changes of dynamic parameters. The motivation was to fix the issue thatvoidon_parameter_event_callback(constrcl_interfaces::msg::ParameterEvent::SharedPtrevent)was called for every parameter change of every node leading to unwanted parameter changes if 2 different nodes had the same parameter name. + +## Dynamic Parameters +Newly added dynamic parameters to: + +## BT Action Nodes Exception Changes +When BT action nodes throw exceptions due to networking or action server failures, they now return a status code ofFAILUREto fail that particular action in the behavior tree to react to. This is in contrast to prior where the exceptions thrown from networking were sent to the root tree which would count as a task-level failure that the tree could not react to. + +## BT Navigator Groot Multiple Navigators +This PR 2627creates separate parameters for groot monitoring for the NavToPose and NavThroughPoses navigator types so you can individually track the state of each behavior tree through the ZMQ publisher. This resolves a long-standing problem after we added multiple navigator types to BT Navigator that you could only view the nav to poses BT execution live. BT.CPP and Groot only support one static ZMQ stream at a time, so there is a bit of a quirk where you must locally reset Groot after switching trees in order to view the live stream of the Nav Through Poses BT, if in use. This is a state of the BT.CPP and Groot libraries and not something we can resolve within Nav2. +There is some thought into the future regarding complete deprecation of live BT monitoring using Groot due to this quirk and the almost-certain infux of tickets on the topic. Groot will however always be supported for visualizing behavior tree XML files and modifications, simply not visualizing the BT execution live during robot navigation. + +## Removed Kinematic Limiting in RPP +The parametersmax_linear_accelandmax_linear_decelwere removed along with the kinematic limiting in the controller causing instabilities. Instead, use a velocity smoother available in the ROS ecosystem if you would like similar behavior. + +## Added Smoother Task Server +A new task server was added which loads smoother plugins and executes them to improve quality of an existing planned path. Smoothing action can be called from a behavior tree using SmoothPath action node.PR 2569implements andPR 2875adds in the first of the plugins using it with a simple smoother. Other smoothers are in development and will be added in the future. + +## Removed Use Approach Velocity Scaling Param in RPP +The parameteruse_approach_linear_velocity_scalingis removed in favor of always on to help in smooth transitions to the goal.This PR 2701implements. + +## Refactored AMCL motion models as plugins +This PR 2642creates plugins for the different motion models currently used in AMCL. This functionality enables users to use any custom motion model by creating it as a plugin and changing the robot_model_type parameter to the name of the plugin in nav2_params.yaml file. This helps to use custom motion models without the need to modify the AMCL source code. + +## Dropping Support for Live Groot Monitoring of Nav2 +It was a great feature idea but never quite panned out, especially after we introduced multiple navigator types in the BT Navigator server. The issue we run into primarily is that Zero-MQ prevents users from producing multiple logger types in the same process. Since BT nav has multiple servers, the swapping between them for viewing has never had a clean hand off causing folks to file tickets or have nasty logs appear or ZMQ crashes in the background. The BT.CPP client for this doesn’t allow us to have a clean shutdown process so we’re left with hoping that ZMQ properly handles the situation, which it rarely does. Further, Groot only supports visualizing one type of tree at a time so for applications often switching between navigator types, its not possible to use a single groot client, causing great frustration. +So, what I propose here is to remove live monitoring of the BT from Nav2.We can still use Groot to modify, visualize, and generally work with behavior trees, the only thing being removed is to live view the executing behavior tree as Nav2 is currently executing it (it used to light up the boxes of the current nodes). This was of dubious value anyhow, since the tree ticks so fast its difficult to visualize and get meaningful insights into things as the system is moving so quickly. + +## Replanning Only if Path is Invalid +This PR 2591creates two new condition BT node to facilitate replanning only if path becomes invalid rather than constantly replanning. These new nodes were integrated into the default BT. + +## Fix CostmapLayer clearArea invert param logic +This PR 2772fixes the invert paramlogic of the CostmapLayer clearArea function. Hence correcting the behavior of the clearAroundRobot and clearExceptRegion services and their corresponding BT actions. + +## Dynamic Composition +This PR 2750provides a optional bringup based on ROS2 dynamic composition for users. It can be used to compose all Nav2 nodes in a single process instead of launching these nodes separately, which is useful for embedded systems users that need to make optimizations due to harsh resource constraints. it’s used by default, but can be disabled by using the launch argumentuse_composition:=False. +Some experiments to show performance improvement of dynamic composition, and the cpu and memory are captured bypsutil: +The way of dynamic composition consumes lower memory(saves ~70%), and lower cpu (saves ~13%) than normal multiple processes. + +## BT Cancel Node +This PR 2787caters the users with an abstract node to develop cancel behaviors for different servers present in the Nav2 stack such as the controller_server, recovery_server and so on. As a start, this PR also provides theCancelControlbehavior to cancel the goal given to the controller_server. As an addition to theCancelControlThis PR 2856provides the users with the option to cancel the recoveries such as thebackup,spinandwait. + +## BT PathLongerOnApproach Node +In thePR, a new Decorator BT node known asPathLongerOnApproachhas been added to provide with the functionality to check and potentially handle longer path generated due to an obstacle in the given goal proximity. To demonstrate this functionality, a new BTnavigate_to_pose_w_replanning_goal_patience_and_recovery.xmlwould serve both as an example and ready-to-use BT for a specific application that wishes to optimize their process cycle time. Demo of the developed BT can be seen below, where the robot pauses when close to a goal to see if the dynamic obstacle moves out of the way. Else, it executes the replan: +Obstacle does not clear at all, withobstacle_clearance_timeto be 3 seconds: +Obstacle clears and you can see the robot pass through the (could have been ideally the) same path: + +## BT TruncatePathLocal Node +In thePR 2753, a new Action BT node namedTruncatePathLocalhas been added to extract a bounded-length path section near robot to be used e.g. for collision checking or computationally expensive smoothers + +## Constrained Smoother +Inthe PR 2753, a new Smoother namednav2_constrained_smoother::ConstrainedSmootherhas been added to optimize various path criteria such as smoothness or distance from obstacles, maintaining minimum turning radius + +## Replanning at a Constant Rate and if the Path is Invalid +This PR 2804introduces a new behavior tree that navigates to pose with consistent replanning and if the path becomes invalid. +To facilitate the new behavior tree a new condition node PathExpiringTimer was introduced to trigger replanning at a consistent rate. + +## Euclidean Distance 2D +This PR 2865changes Euclidean distance calculation throughout nav2 to project on to the XY plane (i.e. discard any information related to components in Z). +This may potentially subtly change the way certain BT nodes, BT Navigators, controller servers, planner servers, and RPP behave if using custom plugins outside the Nav2 ecosystem. + +## Recovery To Behavior +This PR 2867renames the nav2_recoveries to nav2_behaviors. +In navigation_launch.py recoveries_server -> behavior_server and nav2_recoveries -> nav2_behaviors. +In nav2_params.yaml recovery_plugins -> behavior_plugins and nav2_recoveries -> nav2_behaviors. + +## Respawn Support in Launch and Lifecycle Manager +PR 2752enables respawn support in Nav2. In the launch files, you may setuse_respawntotrueto enable respawning of servers that crash. This is only available in non-composed systems, since in composed systems, all of the nodes are under a single process and a crash anywhere will bring everything down (including the lifecycle manager itself). Even if the container was set to respawn, it would only respawn the empty container, not with all of the components loaded into it. +That PR also enables the lifecycle manager to check if a system goes down due to a crash. If so, it allows the manager to check if the server comes back online within a given timeout period. If it does, it will automatically retransition the system back up to active to continue on its task automatically. + +## New Nav2 Velocity Smoother +PR 2964introduces thenav2_velocity_smootherfor smoothing velocity commands from Nav2 to a robot controller by velocity, acceleration, and deadband constraints. SeeVelocity Smootherfor more details. It is not included in the default bringup batteries included fromnav2_bringup. + +## Goal Checker API Changed +PR 2965adds an extra argument in the initialize function of thenav2_core::GoalCheckerclass. +The extra argument is a costmap_ros pointer. This is used to check if the goal is in collision, so that we can avoid moving towards the goal and replanning can be initiates using some BT plugin. + +## Added Assisted Teleop +PR 2904adds a new behavior for assisted teleop along with two new BT nodes AssistedTeleop and CancelAssistedTeleop. + +Code Examples: + +Language: unknown +File: PoseStamped +``` +def +main +(): +rclpy +. +init +() +navigator += +BasicNavigator +() +# Set our demo's initial pose +initial_pose += +PoseStamped +() +... +populate +pose +... +navigator +. +setInitialPose +( +initial_pose +) +# Wait for navigation to fully activate +navigator +. +waitUntilNav2Active +() +# Go to our demos first goal pose +goal_pose += +PoseStamped +() +... +populate +pose +... +navigator +. +goToPose +( +goal_pose +) +while +not +navigator +. +isTaskComplete +(): +feedback += +navigator +. +getFeedback +() +... +do +something +with +feedback +... +# Basic navigation timeout +if +Duration +. +from_msg +( +feedback +. +navigation_time +) +> +Duration +( +seconds += +600.0 +): +navigator +. +cancelNav +() +result += +navigator +. +getResult +() +if +result +== +TaskResult +. +SUCCEEDED +: +print +( +'Goal succeeded!' +) +elif +result +== +TaskResult +. +CANCELED +: +print +( +'Goal was canceled!' +) +elif +result +== +TaskResult +. +FAILED +: +print +( +'Goal failed!' +) +``` + +Language: unknown +File: BtServiceNode +``` +/** +* @brief Function to perform some user-defined operation upon successful +* completion of the service. Could put a value on the blackboard. +* @param response can be used to get the result of the service call in the BT Node. +* @return BT::NodeStatus Returns SUCCESS by default, user may override to return another value +*/ +virtual +BT +:: +NodeStatus +on_completion +( +std +:: +shared_ptr +< +typename +ServiceT +:: +Response +> +/*response*/ +) +{ +return +BT +:: +NodeStatus +:: +SUCCESS +; +} +``` diff --git "a/exported_docs/nav2/General Tutorials\357\203\201.txt" "b/exported_docs/nav2/General Tutorials\357\203\201.txt" new file mode 100644 index 0000000..2e2bea3 --- /dev/null +++ "b/exported_docs/nav2/General Tutorials\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: General Tutorials +URL: https://docs.nav2.org/tutorials/index.html +Section: tutorials/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/Get Backtrace in ROS 2 _ Nav2\357\203\201.txt" "b/exported_docs/nav2/Get Backtrace in ROS 2 _ Nav2\357\203\201.txt" new file mode 100644 index 0000000..6e4d934 --- /dev/null +++ "b/exported_docs/nav2/Get Backtrace in ROS 2 _ Nav2\357\203\201.txt" @@ -0,0 +1,268 @@ +Title: Get Backtrace in ROS 2 / Nav2 +URL: https://docs.nav2.org/tutorials/docs/get_backtrace.html#overview +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This document explains one set of methods for getting backtraces for ROS 2 and Nav2. +There are many ways to accomplish this, but this is a good starting point for new C++ developers without GDB experience. +The following steps show ROS 2 users how to modify the Nav2 stack to get traces from specific servers when they encounter a problem. +This tutorial applies to both simulated and physical robots. +This will cover how to get a backtrace from a specific node usingros2run, from a launch file representing a single node usingros2launch, and from a more complex orchestration of nodes. +By the end of this tutorial, you should be able to get a backtrace when you notice a server crashing in ROS 2. + +## Preliminaries +GDB is the most popular debugger for C++ on Unix systems. +It can be used to determine the reason for a crash and track threads. +It may also be used to add breakpoints in your code to check values in memory a particular points in your software. +Using GDB is a critical skill for all software developers working on C/C++. +Many IDEs will have some kind of debugger or profiler built in, but with ROS, there are few IDEs to choose. +Therefore it’s important to understand how to use these raw tools you have available rather than relying on an IDE to provide them. +Further, understanding these tools is a fundamental skill of C/C++ development and leaving it up to your IDE can be problematic if you change roles and no longer have access to it or are doing development on the fly through an ssh session to a remote asset. +Using GDB luckily is fairly simple after you have the basics under your belt. +The first step is to add-gto your compiler flags for the ROS package you want to profile / debug. +This flag builds debug symbols that GDB and valgrind can read to tell you specific lines of code in your project are failing and why. +If you do not set this flag, you can still get backtraces but it will not provide line numbers for failures. +Be sure to remove this flag after debugging, it will slow down performance at run-time. +Adding the following line to yourCMakeLists.txtfor your project should do the trick. +If your project already has aadd_compile_options(), you can simply add-gto it. +Then simply rebuild your workspace with this packagecolconbuild--packages-select. +It may take a little longer than usual to compile. +Now you’re ready to debug your code! +If this was a non-ROS project, at this point you might do something like below. +Here we’re launching a GDB session and telling our program to immediately run. +Once your program crashes, it will return a gdb session prompt denoted by(gdb). +At this prompt you can access the information you’re interested in. +However, since this is a ROS project with lots of node configurations and other things going on, this isn’t a great option for beginners or those that don’t like tons of commandline work and understanding the filesystem. +Below are sections to describe the 3 major situations you could run into with ROS 2-based systems. +Read the section that best describes the problem you’re attempting to solve. + +## From a Node +Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 node. +While we could set this up through the commandline with some knowledge of the ROS 2 file system, we can instead use the launch--prefixoption the kind folks at Open Robotics provided for us. +--prefixwill execute some bits of code before ourros2command allowing us to insert some information. +If you attempted to dogdbexrun--argsros2runas analog to our example in the preliminaries, you’d find that it couldn’t find theros2command. +If you’re even more clever, you’d find that trying to source your workspace would also fail for similar reasons. +Rather than having to revert to finding the install path of the executable and typing it all out, we can instead use--prefix. +This allows us to use the sameros2runsyntax you’re used to without having to worry about some of the GDB details. +Just as before, this prefix will launch a GDB session and run the node you requested with all the additional commandline arguments. +You should now have your node running and should be chugging along with some debug printing. +Once your server crashes, you’ll see a prompt like below. At this point you can now get a backtrace. +In this session, typebacktraceand it will provide you with a backtrace. +Copy this for your needs. +For example: +In this example you should read this in the following way, starting at the bottom: +These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on. +Then you can deduce why it crashed. +When you are done with GDB, typequitand it will exit the session and kill any processes still up. +It may ask you if you want to kill some threads at the end, say yes. + +## From a Launch File +Just as in our non-ROS example, we need to setup a GDB session before launching our ROS 2 launch file. +While we could set this up through the commandline, we can instead make use of the same mechanics that we did in theros2runnode example, now using a launch file. +In your launch file, find the node that you’re interested in debugging. +For this section, we assume that your launch file contains only a single node (and potentially other information as well). +TheNodefunction used in thelaunch_rospackage will take in a fieldprefixtaking a list of prefix arguments. +We will insert the GDB snippet here with one change from our node example, use ofxterm.xtermwill pop up a new terminal window to show and interact with GDB. +We do this because of issues handlingstdinon launch files (e.g. if you hit control+C, are you talking to GDB or launch?). +Seethis ticketfor more information. +See below for an example debugging SLAM Toolbox. +Just as before, this prefix will launch a GDB session, now inxtermand run the launch file you requested with all the additional launch arguments defined. +Once your server crashes, you’ll see a prompt like below, now in thextermsession. At this point you can now get a backtrace. +In this session, typebacktraceand it will provide you with a backtrace. +Copy this for your needs. +See the example trace in the section above for an example. +These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on. +Then you can deduce why it crashed. +When you are done with GDB, typequitand it will exit the session and kill any processes still up. +It may ask you if you want to kill some threads at the end, say yes. + +## From Large Project +Working with launch files with multiple nodes is a little different so you can interact with your GDB session without being bogged down by other logging in the same terminal. +For this reason, when working with larger launch files, its good to pull out the specific server you’re interested in and launching it separately. +These instructions are targeting Nav2, but are applicable to any large project with many nodes of any type in a series of launch file(s). +As such, for this case, when you see a crash you’d like to investigate, its beneficial to separate this server from the others. +If your server of interest is being launched from a nested launch file (e.g. an included launch file) you may want to do the following: +Alternatively, if you server of interest is being launched in these files directly (e.g. you see aNode,LifecycleNode, or inside aComponentContainer), you will need to separate this from the others: +Once your server crashes, you’ll see a prompt like below in the specific server’s terminal. At this point you can now get a backtrace. +In this session, typebacktraceand it will provide you with a backtrace. +Copy this for your needs. +See the example trace in the section above for an example. +These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on. +Then you can deduce why it crashed. +When you are done with GDB, typequitand it will exit the session and kill any processes still up. +It may ask you if you want to kill some threads at the end, say yes. + +## From Nav2 Bringup +To debug directly from the nav2 bringup launch files you may want to do the following: +Once your server crashes, you’ll see a prompt like below in the xterm window. At this point you can now get a backtrace. +In this session, typebacktraceand it will provide you with a backtrace. +Copy this for your needs. +See the example trace in the section above for an example. +These traces take some time to get used to reading, but in general, start at the bottom and follow it up the stack until you see the line it crashed on. +Then you can deduce why it crashed. +When you are done with GDB, typequitand it will exit the session and kill any processes still up. +It may ask you if you want to kill some threads at the end, say yes. + +## Automatic backtrace on crash +Thebackward-cpplibrary provides beautiful stack traces, and thebackward_roswrapper simplifies its integration. +Just add it as a dependency andfind_packageit in your CMakeLists and the backward libraries will be injected in all your executables and libraries. + +Code Examples: + +Language: unknown +File: colconbuild--packages-select +``` +add_compile_options +( +-g +) +``` + +Language: unknown +File: (gdb) +``` +gdb +ex +run +--args +/path/to/exe/program + +``` + +Language: unknown +File: ros2run +``` +ros2 +run +--prefix +'gdb -ex run --args' + + +--all-other-launch +arguments + +``` + +Language: unknown +File: ros2run +``` +( +gdb +) +``` + +Language: unknown +File: backtrace +``` +( +gdb +) +backtrace + +#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 +#1 0x00007ffff79cc859 in __GI_abort () at abort.c:79 +#2 0x00007ffff7c52951 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +#3 0x00007ffff7c5e47c in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +#4 0x00007ffff7c5e4e7 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +#5 0x00007ffff7c5e799 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +#6 0x00007ffff7c553eb in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +#7 0x000055555555936c in std::vector >::_M_range_check ( +this += +0x5555555cfdb0, +__n += +100 +) +at +/usr/include/c++/9/bits/stl_vector.h:1070 + +#8 0x0000555555558e1d in std::vector >::at (this=0x5555555cfdb0, +__n += +100 +) +at +/usr/include/c++/9/bits/stl_vector.h:1091 + +#9 0x000055555555828b in GDBTester::VectorCrash (this=0x5555555cfb40) +at +/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/gdb_test_node.cpp:44 + +#10 0x0000555555559cfc in main (argc=1, argv=0x7fffffffc108) +at +/home/steve/Documents/nav2_ws/src/gdb_test_pkg/src/main.cpp:25 + +``` + +Language: unknown +File: stdin +``` +start_sync_slam_toolbox_node += +Node +( +parameters += +[ +get_package_share_directory +( +"slam_toolbox" +) ++ +'/config/mapper_params_online_sync.yaml' +, +{ +'use_sim_time' +: +use_sim_time +} +], +package += +'slam_toolbox' +, +executable += +'sync_slam_toolbox_node' +, +name += +'slam_toolbox' +, +prefix += +[ +'xterm -e gdb -ex run --args' +], +output += +'screen' +) +``` + +Language: unknown +File: xterm +``` +( +gdb +) +``` + +Language: unknown +File: --ros-args-r__node:=--params-file/absolute/path/to/params.yaml +``` +( +gdb +) +``` + +Language: unknown +File: ros2launchnav2_bringuptb3_simulation_launch.pyuse_composition:=False +``` +( +gdb +) +``` diff --git "a/exported_docs/nav2/GetPoseFromPath\357\203\201.txt" "b/exported_docs/nav2/GetPoseFromPath\357\203\201.txt" new file mode 100644 index 0000000..3215087 --- /dev/null +++ "b/exported_docs/nav2/GetPoseFromPath\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: GetPoseFromPath +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/GetPoseFromPath.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: -2 +``` + +``` diff --git "a/exported_docs/nav2/Getting Involved\357\203\201.txt" "b/exported_docs/nav2/Getting Involved\357\203\201.txt" new file mode 100644 index 0000000..410de40 --- /dev/null +++ "b/exported_docs/nav2/Getting Involved\357\203\201.txt" @@ -0,0 +1,97 @@ +Title: Getting Involved +URL: https://docs.nav2.org/development_guides/involvement_docs/index.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Getting Involved +If you’re interested in getting involved in Navigation 2, first of all, welcome! +We encourage everyone to get involved from students, to junior developers, to senior developers, and executives. +There’s something to do for everyone from bug fixes, to feature development, new algorithms, and refactoring. +All ROS 2 TSC Working Groups have their meetings on theworking group calendar. +Here, you can find the date and time of the Navigation2 working group meeting. Make sure you’re checking in your local timezone. +From this calendar, you can add yourself to the event so it will appear on your google calendar and get the event link to the call through Google Hangouts. +We encourage everyone interested to come to the meeting to introduce yourself, your project, and see what everyone is working on. +Further,ROS Discourseis a good place to follow larger discussions happening in the community and announcements. This isnotthe correct place to post questions or ask for assistance. Please visitROS Answersfor Q&A. +Lastly, we have aCommunity Slackwhere we chat in real-time about topics in public channels or sidebar maintainers on individual projects via PMs. If you’re interested in contributing to Nav2, this is a great place to join! +If you’re looking to contribute code or bugs, please see the Process section below. +Over time, for developers that have an interest and have shown technical competence in an area of the stack, we elevate developers to a maintainers status. +That allows push rights to our protected branches, first-reviewers rights, and getting your name onAbout and Contact. +There currently is not a clear process for getting to be a maintainer, but if you’ve been involved and contributing over a duration of several months, you may be a good candidate and should email the project lead listed onAbout and Contact. + +## Process +After you’ve introduced yourself in a working group meeting (recommended, not required), you’re ready to get started! +We recommend a typical open-source project flow and value detail and transparency. +If you commit to something and need to pull back, say so. +We all know priorities change and appreciate the heads up so that task can go into the open queue of tasks. +The process is simple and is as follow: +Note: We take code quality seriously and strive for high-quality and consistent code. +We make use of the linting and static analysis tools provided in ROS 2 (ament_cpplint,ament_uncrustify,ament_cppcheck, etc). +All PRs are built in CI with the appropriate ROS distributions and run through a set of unit and system level tests including static analysis. +You can see the results of these tests in the pull request. +It is expected for feature development for tests to cover this work to be added. +If any documentation must be updated due to your changes, that should be included in your pull request. + +## Licensing +Licensing is very important to open source projects. It helps ensure the +software continues to be available under the terms that the author +desired. +Because much of the source code is ported from other ROS 1 projects, each +package has it’s own license. Contributions should be made under the predominant +license of that package. Entirely new packages should be made available under +theApache 2.0 license. +A license tells you what rights you have as a developer, as provided by +the copyright holder. It is important that the contributor fully +understands the licensing rights and agrees to them. Sometimes the +copyright holder isn’t the contributor, such as when the contributor is +doing work on behalf of a company. +If for some reason Apache 2.0 or BSD licenses are not appropriate for your work, please get in contact with a project maintainer and discuss your concerns or requirements. +We may consider special exceptions for exceptional work, within reason (we will not accept any licenses that makes it unsuitable for commercial use). + +## Developer Certification of Origin (DCO) +To make a good faith effort to ensure licensing criteria are met, +Nav2 encourages the Developer Certificate of Origin (DCO) process +to be followed. +The DCO is an attestation attached to every contribution made by a +developer. In the commit message of the contribution, (described more +fully later in this document), the developer simply adds aSigned-off-bystatement and thereby agrees to the DCO. +In practice, its easier to justgitcommit-s-m"commitmessage.". +Where-sadds this automatically. +If you forgot to add this to a commit, it is easy to append via:gitcommit--amend-s. +When a developer submits a patch, it is a commitment that the +contributor has the right to submit the patch per the license. The DCO +agreement is shown below and athttp://developercertificate.org/. + +Code Examples: + +Language: unknown +File: gitcommit--amend-s +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate open + source license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same open source license (unless + I am permitted to submit under a different license), as + Indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the open source license(s) + involved. + +``` diff --git "a/exported_docs/nav2/Getting Started\357\203\201.txt" "b/exported_docs/nav2/Getting Started\357\203\201.txt" new file mode 100644 index 0000000..1dd1f7a --- /dev/null +++ "b/exported_docs/nav2/Getting Started\357\203\201.txt" @@ -0,0 +1,101 @@ +Title: Getting Started +URL: https://docs.nav2.org/getting_started/index.html +Section: development_guides/index.html +-------------------------------------------------------------------------------- + + +## Installation +Jazzy introduced the new Gazebo modern simulator, replacing Gazebo Classic. +Thus, for Jazzy and newer, the installation packages and instructions are slightly different to pull in the appropriate packages. +ForJazzy and newer, install the Turtlebot 3 & 4 packages for Gazebo Modern. It should be automatically installed withnav2_bringup: +ForIron and older, install Turtlebot 3 packages for gazebo classic: + +## Running the Example + + +## Navigating +After starting, the robot initially has no idea where it is. By default, +Nav2 waits for you to give it an approximate starting position. Take a look +at where the robot is in the Gazebo world, and find that spot on the map. Set +the initial pose by clicking the “2D Pose Estimate” button in RViz, and then +down clicking on the map in that location. You set the orientation by dragging +forward from the down click. +If you are using the defaults so far, the robot should look roughly like this. +If you don’t get the location exactly right, that’s fine. Nav2 will refine +the position as it navigates. You can also, click the “2D Pose +Estimate” button and try again, if you prefer. +Once you’ve set the initial pose, the transform tree will be complete and +Nav2 will be fully active and ready to go. You should see the robot and particle +cloud now. +Next, click the “Navigaton2 Goal” button and choose a destination. +This will call the BT navigator to go to that goal through an action server. +You can pause (cancel) or reset the action through the Nav2 rviz plugin shown. +Now watch the robot go! + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +sudo +apt +install +ros--navigation2 +sudo +apt +install +ros--nav2-bringup + +``` + +Language: unknown +File: nav2_bringup +``` +sudo +apt +install +ros--nav2-minimal-tb* + +``` + +Language: unknown +File: nav2_bringup +``` +sudo +apt +install +ros--turtlebot3-gazebo + +``` + +Language: unknown +File: nav2_bringup +``` +source +/opt/ros//setup.bash + +export +TURTLEBOT3_MODEL += +waffle +# Iron and older only with Gazebo Classic +export +GAZEBO_MODEL_PATH += +$GAZEBO_MODEL_PATH +:/opt/ros//share/turtlebot3_gazebo/models +# Iron and older only with Gazebo Classic +``` + +Language: unknown +File: nav2_bringup +``` +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +headless: += +False + +``` diff --git "a/exported_docs/nav2/GloballyUpdatedGoal\357\203\201.txt" "b/exported_docs/nav2/GloballyUpdatedGoal\357\203\201.txt" new file mode 100644 index 0000000..5ea16e5 --- /dev/null +++ "b/exported_docs/nav2/GloballyUpdatedGoal\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: GloballyUpdatedGoal +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GloballyUpdatedGoal.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/GoalAlignCritic\357\203\201.txt" "b/exported_docs/nav2/GoalAlignCritic\357\203\201.txt" new file mode 100644 index 0000000..b0cdb76 --- /dev/null +++ "b/exported_docs/nav2/GoalAlignCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: GoalAlignCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/goal_align.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: GoalAlignCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/GoalCheckerSelector\357\203\201.txt" "b/exported_docs/nav2/GoalCheckerSelector\357\203\201.txt" new file mode 100644 index 0000000..aa39e2e --- /dev/null +++ "b/exported_docs/nav2/GoalCheckerSelector\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: GoalCheckerSelector +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/GoalCheckerSelector.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: transientlocal +``` + +``` diff --git "a/exported_docs/nav2/GoalDistCritic\357\203\201.txt" "b/exported_docs/nav2/GoalDistCritic\357\203\201.txt" new file mode 100644 index 0000000..0dae3c0 --- /dev/null +++ "b/exported_docs/nav2/GoalDistCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: GoalDistCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/goal_dist.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: GoalDistCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/GoalReached\357\203\201.txt" "b/exported_docs/nav2/GoalReached\357\203\201.txt" new file mode 100644 index 0000000..8c16d93 --- /dev/null +++ "b/exported_docs/nav2/GoalReached\357\203\201.txt" @@ -0,0 +1,46 @@ +Title: GoalReached +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GoalReached.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameter + + +## Example + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +bt_navigator +: +ros__parameters +: +# other bt_navigator parameters +transform_tolerance +: +0.1 +goal_reached_tol +: +0.25 +``` + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/GoalUpdated\357\203\201.txt" "b/exported_docs/nav2/GoalUpdated\357\203\201.txt" new file mode 100644 index 0000000..f8b4896 --- /dev/null +++ "b/exported_docs/nav2/GoalUpdated\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: GoalUpdated +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/GoalUpdated.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/GoalUpdater\357\203\201.txt" "b/exported_docs/nav2/GoalUpdater\357\203\201.txt" new file mode 100644 index 0000000..7b2f2f4 --- /dev/null +++ "b/exported_docs/nav2/GoalUpdater\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: GoalUpdater +URL: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/GoalUpdater.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + +``` diff --git "a/exported_docs/nav2/Graceful Controller\357\203\201.txt" "b/exported_docs/nav2/Graceful Controller\357\203\201.txt" new file mode 100644 index 0000000..391b386 --- /dev/null +++ "b/exported_docs/nav2/Graceful Controller\357\203\201.txt" @@ -0,0 +1,125 @@ +Title: Graceful Controller +URL: https://docs.nav2.org/configuration/packages/configuring-graceful-motion-controller.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Graceful Controller Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: initial_rotation +``` +controller_server +: +ros__parameters +: +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +goal_checker_plugins +: +[ +"goal_checker" +] +controller_plugins +: +[ +"FollowPath" +] +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +required_movement_radius +: +0.5 +movement_time_allowance +: +10.0 +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +stateful +: +True +FollowPath +: +plugin +: +nav2_graceful_controller::GracefulController +transform_tolerance +: +0.1 +motion_target_dist +: +0.6 +initial_rotation +: +true +initial_rotation_min_angle +: +0.75 +final_rotation +: +true +allow_backward +: +false +k_phi +: +3.0 +k_delta +: +2.0 +beta +: +0.4 +lambda +: +2.0 +v_linear_min +: +0.1 +v_linear_max +: +1.0 +v_angular_max +: +5.0 +slowdown_radius +: +1.5 +``` diff --git "a/exported_docs/nav2/Groot - Interacting with Behavior Trees\357\203\201.txt" "b/exported_docs/nav2/Groot - Interacting with Behavior Trees\357\203\201.txt" new file mode 100644 index 0000000..565a6ff --- /dev/null +++ "b/exported_docs/nav2/Groot - Interacting with Behavior Trees\357\203\201.txt" @@ -0,0 +1,86 @@ +Title: Groot - Interacting with Behavior Trees +URL: https://docs.nav2.org/tutorials/docs/using_groot.html#adding-a-custom-node +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +Grootis the companion application of theBehaviorTree.CPPlibrary used to create, edit, and visualize behavior trees. +Behavior Trees are deeply integrated into Nav2, used as the main method of orchestrating task server logic across a complex navigation and autonomy stack. +Behavior Trees, in short BTs, consist of many nodes completing different tasks and control the flow of logic, similar to a Hierarchical or Finite State Machine, but organized in a tree structure. +These nodes are of types:Action,Condition,Control, orDecorator, and are described in more detail inNavigation ConceptsandBehaviorTree.CPP. +Writing a New Behavior Tree Pluginoffers a well written example of creating a simpleActionnode if creating new BT nodes is of interest. This tutorial will focus solely on launching Groot, visualizing a Behavior Tree, and modifying that tree for a given customization, assuming a library of BT nodes. Luckily, Nav2 provides a robust number of BT nodes for your use out of the box, enumerated inNavigation Plugins. +A BT configuration file in BehaviorTree.CPP is an XML file. This is used to dynamically load the BT node plugins at run-time from the appropriate libraries mapped to their names. The XML format is definedin detail here. Therefore, Groot needs to have a list of nodes it has access to and important metadata about them like their type and ports (or parameters). We refer to this as the “palette” of nodes later in the tutorial. +In the video above you can see Groot side-by-side with RVIz and a test platform 100% equipped with ROS-enabled hardware from SIEMENS. +Groot not only displays the current Behavior Tree while the robot is operating. Note: Before ROS 2 Humble, live Groot behavior tree monitoring during execution was supported in Nav2. This was removed due to buggy support in BT.CPP / Groot for changing behavior trees on the fly, seeGalactic to Humblefor more details. + +## Visualize Behavior Trees +To display a Behavior Tree like that inFigure 3, we will first start the Groot executable. +Out of the box, Groot can only display Behavior Trees and nodes that are from the defaults in BT.CPP, since it does not know anything about Nav2 or your other projects. +Therefore, we must point Groot to our palette, or index, of Nav2 / custom behavior tree nodes: +If you select the default treenavigate_w_replanning_and_recovery.xml, then a Groot editor should look likeFigure 3. + +## Edit Behavior Trees +Now that you have a Nav2 BT open in Groot in editor mode, you should be able to trivially modify it using the GUI. +Starting from a screen like that shown inFigure 3, you can pull in new nodes from the side panel to add them to the workspace. +You may then connect the nodes using a “drag and drop” motion between the node’s input and output ports to assemble the new nodes into the tree. +If you select a given node, you can change metadata about it such as its name or values of parameterizable ports. When you’re done modifying, simply save the new configuration file and use that on your robot the next time! + +## Adding A Custom Node +Each node in the behavior tree holds a specialized function. +Sometimes, its useful to create new nodes and add them to your palette during the design process - perhaps before the implementations themselves exist. +This helps designers abstract away the implementation specifics of the nodes from the higher level logic of the tree itself and how they’d like to interact with a given node (e.g. type, ports, etc). +Within Groot, you may create new custom nodes to add to your tree and export these new nodes back to your palette. +Implementing the node itself needs to be done separately from Groot, which is described inWriting a New Behavior Tree Plugin. +Creating a new custom node can be started by clicking the orange marked icon inFigure 4, while Groot is in Editor mode. +This should load a new window, similar toFigure 5. +In this new window, it asks you to fill in the metadata about this new node, in order to create it. +It will ask you for standard information such as name (green box), type of node (orange box), and any optional ports for parameterization or access to blackboard variables (blue box). +After completing, selectOKinFigure 5, the new custom node should appear in blue in theTreeNode Paletteas inFigure 6. +Before starting to create a new BT based on the new custom nodes, it is recommend to export the newly created nodes to save in case of Groot crashing. +This can be performed with the icon highlighted in green fromFigure 6. +The resulting XML output from the node created inFigure 5can be seen below. +You can see more examples inNav2’s BT Node Palette XML. + +Code Examples: + +Language: unknown +File: Action +``` + + + + +coffee + + +Sense +of +life + + +rolling +target + + + + +``` diff --git "a/exported_docs/nav2/Humble to Iron\357\203\201.txt" "b/exported_docs/nav2/Humble to Iron\357\203\201.txt" new file mode 100644 index 0000000..55f29cd --- /dev/null +++ "b/exported_docs/nav2/Humble to Iron\357\203\201.txt" @@ -0,0 +1,141 @@ +Title: Humble to Iron +URL: https://docs.nav2.org/migration/Humble.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## New Behavior-Tree Navigator Plugins +New inPR 3345, the navigator types are exposed to users as plugins that can be replaced or new navigator types added. The default behaviors of navigate to pose and navigate through poses continue to be default behavior but are now customizable with new action interface definitions. These plugins implement thenav2_core::BehaviorTreeNavigatorbase class, which must process the action request, feedback, and completion messages. The behavior tree is handled by this base class with as much general logic as possible abstracted away from users to minimize repetition. +SeeWriting a New Navigator Pluginfor a tutorial about writing new navigator plugins. + +## Added Collision Monitor +PR 2982adds new safety layer operating independently of Nav2 stack which ensures the robot to control the collisions with near obstacles, obtained from different sensors (LaserScan, PointCloud, IR, Sonars, etc…). SeeCollision Monitorfor more details. It is not included in the default bringup batteries included fromnav2_bringup. + +## Removed use_sim_time from yaml +PR #3131makes it possible to set the use_sim_time parameter from the launch file for multiple nodes instead of individually via the yaml files. If using the Nav2 launch files, you can optionally remove the use_sim_time parameter from your yaml files and set it via a launch argument. + +## Run-time Speed up of Smac Planner +The core data structure of the graph implementation in the Smac Planner framework was swapped out inPR 3201to using a specialized unordered map implementation. This speeds up the planner by 10% on trivial requests and reports up to 30% on complex plans that involve numerous rehashings. + +## Recursive Refinement of Smac and Simple Smoothers +The number of recursive refinements for the Simple and Smac Planner Smoothers have been exposed under therefinement_numparameter. Previous behavior had this hardcoded ifdo_refinement=Trueto4. Now, default is2to help decrease out-of-the-box over smoothing reducing in paths closer to collision than probably ideal, but old behavior can be achieved by changing this to4. + +## Simple Commander Python API +PR 3159and follow-up PRs add in Costmap API in Python3 simple commander to receiveOccupancyGridmessages from Nav2 and be able to work with them natively in Python3, analog to the C++ Costmap API. It also includes a line iterator and collision checking object to perform footprint or other collision checking in Python3. See the Simple Commander API for more details. + +## Smac Planner Start Pose Included in Path +PR 3168adds the starting pose to the Smac Planners that was previously excluded during backtracing. + +## Parameterizable Collision Checking in RPP +PR 3204adds makes collision checking for RPP optional (default on). + +## Expanded Planner Benchmark Tests +PR 3218adds launch files and updated scripts for performing objective random planning tests across the planners in Nav2 for benchmarking and metric computation. + +## Smac Planner Path Tolerances +PR 3219adds path tolerances to Hybrid-A* and State Lattice planners to return approximate paths if exact paths cannot be found, within a configurable tolerance aroun the goal pose. + +## costmap_2d_node default constructor +PR #3222changes the constructor used by the standalone costmap node. The new constructor does not set a name and namespace internally so it can be set via the launch file. + +## Feedback for Navigation Failures +PR #3146updates the global planners to throw exceptions on planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application. +The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, or No Valid Path Found. +PR #3248updates the compute path through poses action to report planning failures. These exceptions get reported back to the planner server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application. +The following errors codes are supported (with more to come as necessary): Unknown, TF Error, Start or Goal Outside of Map, Start or Goal Occupied, Timeout, No Valid Path Found and No Waypoints given. +PR #3227updates the controllers to throw exceptions on failures. These exceptions get reported back to the controller server which in turn places a error code on the Behavior Tree Navigatior’s blackboard for use in contextual error handling in the autonomy application. +The following error codes are supported (with more to come as necessary): Unknown, TF Error, Invalid Path, Patience Exceeded, Failed To Make Progress, or No Valid Control. +PR #3251pipes the highest priority error code through the bt_navigator and defines the error code structure. +A new parameter for the the BT Navigator called “error_code_id_names” was added to the nav2_params.yaml to define the error codes to compare. +The lowest error in the “error_code_id_names” is then returned in the action request (navigate to pose, navigate through poses waypoint follower), whereas the code enums increase the higher up in the software stack - giving higher priority to lower-level failures. +The error codes produced from the servers follow the guidelines stated below. +Error codes from 0 to 9999 are reserved for nav2 while error codes from 10000-65535 are reserved for external servers. +Each server has two “reserved” error codes. 0 is reserved for NONE and the first error code in the sequence is reserved for UNKNOWN. +The current implemented servers with error codes are: +This pr also updates the waypoint follower server to throw exceptions on failures. These exceptions get reported back to the server which in turn places a error code on the Behavior Tree Navigator’s blackboard for use in contextual error handling in the autonomy application. +The following errors codes are supported (with more to come as necessary): Unknown and Task Executor Failed. +SeeAdding a New Nav2 Task Serverand the PR for additional information. + +## Costmap Filters +Costmap Filters now are have an ability to be enabled/disabled in run-time by callingtoggle_filterservice for appropriate filter (PR #3229). +Added new binary flip filter, allowing e.g. to turn off camera in sensitive areas, turn on headlights/leds/other safety things or switch operating mode when robot is inside marked on mask areas (PR #3228). + +## Savitzky-Golay Smoother +Adding a new smoother algorithm, the Savitzky-Golay smoother to the smoother server plugin list. See the configuration guideSavitzky-Golay Smootherfor more details. + +## Changes to Map yaml file path for map_server node in Launch +PR #3174adds a way to set the path to map yaml file for the map_server node either from the yaml file or using the launch configuration parametermapgiving priority to the launch configuration parameter.yaml_filenameis no longer strictly required to be present innav2_params.yaml. + +## SmootherSelector BT Node +PR #3283adds a BT node to set the smoother based on a topic or a default. See the configuration guideSimple Smootherfor more details. + +## Publish Costmap Layers +PR #3320adds the ability for the nav2_costmap_2d package to publish out costmap data associated with each layer. + +## Give Behavior Server Access to Both Costmaps +PR #3255adds the ability for a behavior to access the local and global costmap. +To update behaviors, any reference to the global_frame must be updated to the local_frame parameter +along with theconfigurationmethod which now takes in the local and global collision checkers. +Lastly,getResourceInfomust be overridden to returnCostmapInfoType::LOCAL. Other options includeGLOBALif the behavior useses global costmap and/or footprint) +orBOTHif both are required. This allows us to only create and maintain the minimum amount of expensive resources. + +## New Model Predictive Path Integral Controller +The new Nav2 MPPI Controller is a predictive controller - a successor to TEB and pure path tracking MPC controllers - with Nav2. It uses a sampling based approach to select optimal trajectories, optimizing between successive iterations. It contains plugin-based objective functions for customization and extension for various behaviors and behavioral attributes. +See the README.md andModel Predictive Path Integral Controllerpage for more detail. + +## Behavior Tree Uses Error Codes +PR #3324adds three new condition nodes to check for error codes on the blackboard set by action BT nodes which contain them. +TheAreErrorCodesPresentcondition node allows the user to specify the error code from the server along with the error codes to match against. +TheWouldAControllerRecoveryHelpchecks if the active error code is UNKNOWN, PATIENCE_EXCEEDED, FAILED_TO_MAKE_PROGRESS or NO_VALID_CONTROL. +If the error code is a match, the condition returnsSUCCESS. +These error code are potentially able to be cleared by a controller recovery. +TheWouldAPlannerRecoveryHelpchecks if the active error code is UNKNOWN, NO_VALID_CONTROL, or TIMEOUT. +If the error code is a match, the condition returnsSUCCESS. +These error code are potentially able to be cleared by a planner recovery. +TheWouldASmootherRecoveryHelpchecks if the active error code is UNKNOWN, TIMEOUT, FAILED_TO_SMOOTH_PATH, or SMOOTHED_PATH_IN_COLLISION. +If the error code is a match, the condition returnsSUCCESS. +These error code are potentially able to be cleared by a smoother recovery. + +## Load, Save and Loop Waypoints from the Nav2 Panel in RViz +PR #3165provides three new functionalities for the nav2 panel in RViz, they are: +Looping functionality is not specific to the nav2 panel in RViz. Users utilizing nav2_waypoint_follower can take advantage of the changes made to the FollowWaypoint action, by specifying the desired number of loops in the action request that will be eventually sent to the nav2_waypoint_follower server. + +## DWB Forward vs Reverse Pruning +PR #3374adds a newforward_prune_distanceparameter in the DWB controller. It replaces theprune_distancefor forward path shortening, enabled through theshorten_transformed_planboolean parameter. This change allows to use different values for forward and backward path shortening. + +## More stable regulation on curves for long lookahead distances +PR #3414adds a newuse_fixed_curvature_lookaheadparameter to the RPP controller. This makes slowing down on curve not dependent on the instantaneous lookahead point, but instead on a fixed distance set by the parametercurvature_lookahead_dist. + +## Publish Collision Monitor State +PR #3504adds a newstate_topicparameter to the CollisionMonitor. If specified, this optional parameter enables the state topic publisher. The topic reports the currently activated polygon action type and name. + +## Renamed ROS-parameter in Collision Monitor +PR #3513renamesmax_pointsparameter tomin_pointsand changes its meaning. Formerlymax_pointsmeant the maximum number of points inside the area still not triggering the action, whilemin_points- is a minimal number of points starting from the action to be initiated. In other wordsmin_pointsnow should be adjusted asmax_points+1. + +## New safety behavior model “limit” in Collision Monitor +PR #3519adds a new collision monitor behavior modellimitthat restricts maximum linear and angular speed to specific values (linear_limitandangular_limit) if enough points are in the given shape. + +## Velocity smoother applies deceleration when timeout +PR #3512makes the VelocitySmoother apply the deceleration when the input command timeout. + +## PoseProgressChecker plugin +PR #3530adds a newnav2_controller::PoseProgressCheckerplugin. It builds on the behavior of theSimpleProgressCheckerby adding a new parameterrequired_movement_angle, allowing the plugin to considers that there is still progress when there is no translation movement, from the moment there is a rotation movement superior torequired_movement_anglewithin themovement_time_allowance. + +## Allow multiple goal checkers and change parameter progress_checker_plugin(s) name and type +PR #3555initializes the progress checker plugin(s) in the same way as for the goal checker and controller plugins: it is now a list of string and was renamed fromprogress_checker_plugintoprogress_checker_plugins, and the type changed fromstringtovector. This allows the initialization of multiple progress checkers that can be chosen from the addedprogress_checker_idfieldof theFollowPathaction. +Beware that it is a breaking change and that configuration files will need to be updated. + +## IsBatteryChargingCondition BT Node +PR #3553adds a BT node to check if the battery is charging. See the configuration guideIsBatteryChargingfor more details. + +## Behavior Server Error Codes +PR #3569updates the behavior server plugins to provide error codes on failure. + +## New Denoise Costmap Layer Plugin +PR #2567adds the new plugin for filtering noise on the costmap. +Due to errors inVoxelLayerorObstacleLayermeasurements, salt and pepper noise may appear on thecostmap. This noise creates false obstacles that prevent the robot from finding the best path on the map. +The newDenoiseLayerplugin is designed to filter out noise-induced standalone obstacles or small obstacles groups. This plugin allows you to add layer that will filter local or global costmap. +More information aboutDenoiseLayerplugin and how it works could be foundhere. + +## SmacPlannerHybrid viz_expansions parameter +PR #3577adds a new parameter for visualising SmacPlannerHybrid expansions for debug purpose. diff --git "a/exported_docs/nav2/Inflation Layer Parameters\357\203\201.txt" "b/exported_docs/nav2/Inflation Layer Parameters\357\203\201.txt" new file mode 100644 index 0000000..ea77232 --- /dev/null +++ "b/exported_docs/nav2/Inflation Layer Parameters\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Inflation Layer Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/inflation.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/InitialPoseReceived\357\203\201.txt" "b/exported_docs/nav2/InitialPoseReceived\357\203\201.txt" new file mode 100644 index 0000000..e673f8a --- /dev/null +++ "b/exported_docs/nav2/InitialPoseReceived\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: InitialPoseReceived +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/InitialPoseReceived.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/InputAtWaypoint\357\203\201.txt" "b/exported_docs/nav2/InputAtWaypoint\357\203\201.txt" new file mode 100644 index 0000000..0da5dce --- /dev/null +++ "b/exported_docs/nav2/InputAtWaypoint\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: InputAtWaypoint +URL: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/input_at_waypoint.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_waypoint_follower plugin name defined in thewaypoint_task_executor_plugin_idparameter inWaypoint Follower. diff --git "a/exported_docs/nav2/Introduction To Nav2 Specific Nodes\357\203\201.txt" "b/exported_docs/nav2/Introduction To Nav2 Specific Nodes\357\203\201.txt" new file mode 100644 index 0000000..7c2673e --- /dev/null +++ "b/exported_docs/nav2/Introduction To Nav2 Specific Nodes\357\203\201.txt" @@ -0,0 +1,111 @@ +Title: Introduction To Nav2 Specific Nodes +URL: https://docs.nav2.org/behavior_trees/overview/nav2_specific_nodes.html#control-roundrobin +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Action Nodes +Upon completion, these action nodes will returnSUCCESSif the action server believes the action has been completed correctly,RUNNINGwhen still running, and will returnFAILUREotherwise. Note that in the above list, +theClearCostmapServiceaction node isnotan action server client, but a service client. + +## Condition Nodes +The above list of condition nodes can be used to probe particular aspects of the system. Typically they will returnSUCCESSif the condition is true andFAILUREotherwise. +The key condition that is used in the default Nav2 BT isGoalUpdatedwhich is checked asynchronously within particular subtrees. This condition node allows for the behavior described as “If the goal has been updated, then we must replan”. +Condition nodes are typically paired with ReactiveFallback nodes. + +## Decorator Nodes + + +## Control: PipelineSequence +ThePipelineSequencecontrol node re-ticks previous children when a child returnsRUNNING. +This node is similar to theSequencenode, with the additional property that the children prior to the “current” are re-ticked, (resembling the flow of water in a pipe). +If at any point a child returnsFAILURE, all children will be halted and the parent node will also returnFAILURE. UponSUCCESSof thelast nodein the sequence, this node will halt and returnSUCCESS. +To explain this further, here is an example BT that uses PipelineSequence. +Recall that ifAction_A,Action_B, orAction_CreturnedFAILUREat any point of time, the parent would have returnedFAILUREand halted any children as well. +For additional details regarding thePipelineSequenceplease see thePipelineSequence configuration guide. + +## Control: Recovery +The Recovery control node has only two children and returnsSUCCESSif and only if the first child returnsSUCCESS. +If the first child returnsFAILURE, the second child will be ticked. This loop will continue until either: +This node is usually used to link together an action, and a recovery action as the name suggests. The first action will typically be the “main” behavior, +and the second action will be something to be done in case ofFAILUREof the main behavior. Often, the ticking of the second child action will promote the chance the first action will succeed. +In the above example, let’s assumeComputePathToPosefails.ClearLocalCostmapwill be ticked in response, and returnSUCCESS. +Now that we have cleared the costmap, let’s say the robot is correctly able to compute the path andComputePathToPosenow returnsSUCCESS. Then, the parent RecoveryNode will also returnSUCCESSand the BT will be complete. +For additional details regarding theRecoveryNodeplease see theRecoveryNode configuration guide. + +## Control: RoundRobin +The RoundRobin control node ticks its children in a round robin fashion until a child returnsSUCCESS, in which the parent node will also returnSUCCESS. +If all children returnFAILUREso will the parent RoundRobin. +Here is an example BT we will use to walk through the concept. +2. Upon tick of the parent node, the first child (Action_A) is ticked. Let’s assume on tick the child returnsRUNNING. +In this case, no other children are ticked and the parent node returnsRUNNINGas well. +3. Upon the next tick, let’s assume thatAction_AreturnsFAILURE. +This means thatAction_Bwill get ticked next, andAction_Cremains unticked. +Let’s assumeAction_BreturnsRUNNINGthis time. That means the parent RoundRobin node will also returnRUNNING. +4. Upon this next tick, let’s assume thatAction_BreturnsSUCCESS. The parent RoundRobin will now halt all children and returnSUCCESS. +The parent node retains this state information, and will tickAction_Cupon the next tick rather than start fromAction_Alike Step 2 did. +For additional details regarding theRecoveryNodeplease see theRoundRobin configuration guide. + +Code Examples: + +Language: unknown +File: SUCCESS +``` + + + + + + + + + +``` + +Language: unknown +File: FAILURE +``` + + + + + + + + +``` + +Language: unknown +File: FAILURE +``` + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Iron to Jazzy\357\203\201.txt" "b/exported_docs/nav2/Iron to Jazzy\357\203\201.txt" new file mode 100644 index 0000000..7ceb8b9 --- /dev/null +++ "b/exported_docs/nav2/Iron to Jazzy\357\203\201.txt" @@ -0,0 +1,289 @@ +Title: Iron to Jazzy +URL: https://docs.nav2.org/migration/Iron.html#new-collision-monitor-parameter +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## BehaviorTree.CPP upgraded to version 4.5+ +Since we migrated from version 3.8 to 4.5, users must upgrade their XML and source code accordingly. +You can refer to [this page](https://www.behaviortree.dev/docs/migration) for more details, but the main changes are: + +## Added TwistStamped Option for Commands +A new parameterenable_stamped_cmd_velhas been added to all of the publishers and subscribers ofcmd_veland related topics. This allows you to set the publication and subscription of TwistStamped messages over Twist messages to have frame and timestamp information of the set command. For now, this is default tofalseto not change current behavior, but it is planned to makeTwistStampedthe default behavior alongside Gazebo, ROS 2 Control, and related projects. + +## Add VelocityPolygon in Collision Monitor +PR #3708addsVelocityPolgontype in Collision Monitor. This allows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. The tutorial is available in theConfiguring Collision Monitor with VelocityPolygonsection. + +## Change polygon points parameter format in Collision Monitor +PR #4020changes the format of the Polygon points parameter fromvectortostring. This makes the polygon description more uniform across the Collision Monitor and Costmap_2D. +Now we can define a polygon’s points in string that has avector>structure like this"[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]"with a minimum of 4 points described. An example of a Square polygon will be written as follows. + +## Introduction of Soft-Real Time Action Servers +PR #3914adds soft real-time prioritization to the controller server to better ensure resources to time sensitive portions of the codebase. The Simple Action Server now has arealtimeinput field exposed in the Controller Server via the parameteruse_realtime_prioritywhich will set the controller’s execution thread to a higher priority than the rest of the system to meet scheduling deadlines. To use this feature, you use set the following inside of/etc/security/limits.confto give userspace access to elevated prioritization permissions. This is currently only enabled in the Controller Server, who’s execution thread is sensitive to scheduling priorities, but could be set with other threads in the future if found necessary. +The Collision Monitor and Velocity Smoothers also haduse_realtime_priorityadded as well! + +## opennav_coverageProject +A new metapackage exists in:https://github.com/open-navigation/opennav_coveragewhich contains complete coverage navigator plugins, BT nodes, behavior tree demos, and coverage planning server based onFields2Cover. See that project for more information. It is on long-term trajectory for inclusion intoNav2, but there are still yet a few missing features from Fields2Cover before we can integrate that into the main project to be up to snuff in terms of all the major features and capabilities users would expect from a coverage planning system. +If you’d like to see coverage planning in Nav2 directly, please consider contributingto the as-of-yet needed features described here. + +## opennav_dockingProject +A new metapackage exists in:https://github.com/open-navigation/opennav_dockingwhich contains complete automatic charging dock framework, BT nodes, plugins, and demos. +This allows for docking of any type of robot with any type of charging dock in a repeatable and generalized way. +It will be integrated into Nav2 directly soon (Update June 2024: within Nav2 stack directlynav2_docking!) +SeeUsing Docking Serverfor a tutorial on using this new capability! Thanks to NVIDIA for sponsoring this package! + +## Introduce a new Multi-Robot Bringup Launch +PR #3572introduces a new way of bringup tb3 multi-robot that names ascloned_tb3_simulation_launch.pyfor simulation.cloned_tb3_simulation_launch.pyenables to bring up multiple robots with same parameter that described innav2_multirobot_param_all.yaml. And multiple robots are separated by namespaces which are given as a Launch Arguments. +Existingmulti_tb3_simulation_launch.pywhich was utilized in previous is replaced withunique_tb3_simulation_launch.py, allowing for multiple unique robot instances utilizingnav2_multirobot_params_.yamlconfiguration files. + +## New option for the Voxel and Obstacle Layers +PR #3612adds a new MaxWithoutUnknownOverwrite option to combination_method parameter in Voxel and Obstacle Layers. This can be used to make sure that the static map is the dominant source of information, and +easily prevent the robot to go through places that are not present in the static map. + +## use_interpolation RPP Parameter Depreciated +After a distribution of testing by many users, we have depreciated the use_interpolation parameter and it is now default on at all times without the ability to disable. It improves velocity smoothness and overall quality of tracking positively in all cases. + +## Changes to MPPI Goal Critic +The MPPI Goal critic’s formulation is changed to better keep up with speed on approach to goal instead of preemptively slowing too significantly. It also allows you to better use the weight to adjust the degree at which it slows more naturally. This change involves adjusting thethreshold_to_considerto be the same as your prediction horizon (e.g. samples * dt * max speed) for both the goal critic and path follower critic to have a good hand-off between them without deceleration. + +## Changes to MPPI Path Angle Critic +MPPI’s Path Angle critic now has amodesetting to adjust behavior depending on robot’s desired behavioral traits. Previously, it penalized path orientations that deviated far the the robot’s forward orientation to turn the robot towards sharp changes in the path. This is still default (mode:0), but other modes now exist too. +mode:1sets the penalization of path’s relative directions by either forward orientation or the opposite for reversing to allow for true bidirectional motion when one way or another is not preferable for a symmetric robot. This uses only the path’s relative points to the robot to decide which direction to incentivize. +mode:2instead uses the path’s orientations when a feasible path is given from the Smac Planners or the Smoother server’s algorithms. This way, the globally planned orientations are followed rather than the based solely on the path’s relative points. This is useful for non-circular robots in highly confined settings where there may be restricted opportunities to change directions so following the global path’s orientation are required to end in the orientation you require. + +## Changes to MPPI Path Handling For Directionality +MPPI’s Path Align Critic and Path Handler object now have options to utilize the path’s orientation information to force the controller to change directions when and only when requested by a feasible planner. Whenenforce_path_inversionistrue, the path handler will prune the path to the first time the directions change to force the controller to plan to the inversion point and then be set the rest of the path, once in tolerance. The Path Align critic also contains a parameteruse_path_orientationswhich can be paired with it to incentivize aligning the path containing orientation information to better attempt to achieve path inversions where requestedandnot do them when not requested. +See MPPI’s configuration guide for complete information. + +## Addition of new MPPI Cost Critic +Analog to theObstacleCritic, theCostCriticis another obstacle avoiding critic alternative if theObstacleCriticis not working well for you. +This critic uses the inflated costs in the costmap to score rather than distance to obstacles as theObstaclesCriticdoes. +See the configuration guide for more information. + +## MPPI Acceleration +New to Jazzy, MPPI is 45% faster due to a weeks long optimization campaign. Enjoy! + +## Move Error Code Enumerations +PR #3693moves the enumeration codes from the goal to the result section. + +## Substitution in parameter file +Enabled substitution in parameter file. For example, you can write the following +For more information about substitutions syntax, seehere + +## Allow Behavior Server Plugins to Access The Action Result +PR #3704allows behavior servers plugins to access and modify the action result. + +## Smac Planner Debug Param Name Change +debug_visualizationsreplacesviz_expansionsparameter in Hybrid-A* to reflect the new inclusion of footprint debug information being published as well. + +## Smac Planner On Approach to Goal Shortcutting Solutions +PR #3962 adds new paramsanalytic_expansion_max_costandanalytic_expansion_max_cost_overridein extension ofanalytic_expansion_max_lengthin Humble to further limit potential shortcutting of paths near obstacles in close proximity to the goal. +It uses a maximum cost parameter (default200) to tell if an expansion is closer to an obstacle than a user would like. If the expansion is critically close to the goal, then it may override this constraint ifanalytic_expansion_max_cost_overrideisfalse- allowing the constraint to be overridden to find a successful path solution, as it may be required. +This PR also introduces additional analytic expansion scoring logic and edge case handling to improve path qualities by an analog heuristic function. + +## Added GPS Waypoint Follower Server +This PR 2814adds thefollow_gps_waypointsaction server innav2_waypoint_follower. This server accepts a set of GPS goals instead of cartesian goals and provides all the other functionalities available onnav2_waypoint_follower. A new tutorial demonstrating its functionality was also added onPR 70 on navigation2_tutorialsand can be found on the General Tutorials directory on this website. + +## Smac Planner Hybrid-A* New Features +New featuresallow_primitive_interpolationwhich allows for more primitives in the search set,use_quadratic_cost_penaltyto impact the cost penalty order in the traversal and heuristic functions, anddownsample_obstacle_heuristicto optionally not downsample the obstacle heuristic’s costmap were added. The default behavior will remain the same. If you would like to use these new features, please check out the Smac Planner Hybrid-A* configuration guide. + +## New node in nav2_collision_monitor: Collision Detector +In thisPR #3693A new node was introduced in the nav2_collision_monitor: Collision Detector. +It works similarly to the Collision Monitor, but does not affect the robot’s velocity. It will only inform that data from the configured sources has been detected within the configured polygons via message to thecollision_detector_statetopic that might be used by any external module (e.g. switching LED or sound alarm in case of collision). + +## Dynamic enabling/disabling of sources/polygons in Collision Monitor/Detector +In thisPR #3825we added the ability to dynamically enable/disable sources and polygons in the Collision Monitor/Detector. + +## Expose action server’s result timeout +In thisPR #3787the timeout for action server’s result was exposed in all nodes having action servers. +This is because in thisPR #1012in rcl a change was introduced which makes action servers discard a goal handle if the result +is not produced within 10 seconds, when the default was set to 15 minutes before. Since some actions in Nav2 may take more than 10 seconds to complete, the user has now the ability +to set this value through theaction_server_result_timeoutparameter, which defaults to 15 minutes in thebt_navigatorsandwaypoint_followerand to 10 seconds in all other nodes. + +## RewrittenYaml could add new parameters to YAMLs +NowRewrittenYamlwidely used in Nav2 launch-scripts, could do not only substitutions of ROS-parameters existing in original YAML, but rather additions of new parameters, that did not exist in the YAML. Certainly, these parameters should be declared for target ROS-nodes, otherwise they won’t be processed in run-time. In such functionality, they should be expressed in absolute values, separated by a dot. For example, the rewrite for aprune_distanceparameter of aFollowPathnode will look like'controller_server.ros__parameters.FollowPath.prune_distance':'1.0'in aparam_rewritesdictionary ofRewrittenYaml()argument. +The change was intoroduced in the scope ofPR #3785fix. + +## Simple Commander API Allows Multi-Robot Namespacing +The Simple Navigator API now allows multi-robot namespacing by exposing anamespacefield in the constructor to allow you to specify the Nav2 stacks’ namespace for a robot or system. Seethis PR for details. + +## Change duration type in wait_action node +In thisPR #3871the type of duration variable in wait_action node is changed from int to double, which allows you to use floating values for wait_action. + +## The costmap activation fails when required transforms are not available +In thisPR #3866the parameterinitial_transform_timeoutis added to the costmap. The activation of the costmap now fails, +if the transformation from the robot base frame to the global frame does not become available during this timeout. + +## Subtrees Obtain Shared Resources +PR #3911gives all sub-trees in BT.CPP the same shared resources as the main tree (node, shared timeouts, etc). + +## Collision Monitor: added watchdog mechanism based onsource_timeoutparameter with default blocking behavior +PR #3880adds a watchdog mechanism that stops the robot if a source data is not published yet, or if no new data is received within thesource_timeout`parameter, or if impossible to transform data to base frame.source_timeoutparameter can now be set per source: ifsource_timeoutis not set for a source, the value of the nodesource_timeoutparameter is used. +Additionally, this watchdog mechanism can be disabled by settingsource_timeout:0.0. + +## BtActionServer: use native library haltTree() +PR #3950changes the method used byBehaviorTreeEngine::haltAllActionsto halt the BT nodes to the bt.cpp native methodhaltTree(). +Before this change, only the active BT node was halted when finishing the action. After this change, all BT nodes halt() methods are called. This is very convenient to handle cleaning operation (switch off your lights when leaving) in halt(). +Also updated nav2_behavior_tree::BtActionServer::haltTree() to use the same. It is used nowhere in nav2 but is useful for external users (like me) that want for instance to halt the tree on preemption. + +## Global Frame Removed from 2 BT Nodes +The Global Frame was removed fromRemovePassedGoalsandGoalReachedBT nodes and instead using theframe_idof the goal’s headers for transformation. + +## Introduction ofCostmapUpdate.msg +PR #3965introduces a new type of message -CostmapUpdate.msg. It is the update message related to theCostmap.msg. Now instead of sending the whole costmap in every message, such as withCostmap.msg, theCostmapUpdate.msgincludes only the area of the costmap that has changed since the previous update message. TheCostmap.msgis sent only once at the beginning, followed by the messages of theCostmapUpdate.msgtype. The idea is to mimic theOccupancyGrid.msgandOccupancyGridUpdate.msgbehavior. +To activate this feature, the Costmap2D ROS parameteralways_send_full_costmaphas to be set tofalse. +To subscribe toCostmap.msgandCostmapUpdate.msgit is recommended to use theCostmapSubscriberclass. + +## Full Stack Uses Node Clocks +The stack no longer contains wall timers or wall rates. It will now use the node clocks. This will be ROS Time for simulation whenuse_sim_timeis true. Else, it uses a steady clock. + +## New Graceful Motion Controller +PR #4021introduces a new type of controller for differential robots based on a pose-following kinematic control law that generates a smooth and comfortable trajectory. +SeeGraceful Controllerfor more information. + +## Plugin Libraries in BT Navigator Only Includes Custom Nodes +New to Jazzy, theplugin_lib_namesparameter implicitly includes all Nav2 BT nodes automatically. It is only required now to specify additional user-generated BT plugins to load. + +## New RViz Plugin for selecting Planners, Controllers, Goal Checkers, Progress Checkers and Smoothers +In PR #4091a new RViz plugin was added to select the planner, controller, goal checker, progress checker, and smoother on the fly. +The primary goal of this plugin is to facilitate the developers and easy integration testing of their configuration before deploying the robot in the intended application. +In order to facilitate the dynamic selection of the specified components, the BT selector nodes for all these components were utilized and were updated to all the relevant BT nodes. +Here we can see the working demo of the plugin: +In the GIF, it can be seen that there are two controller_ids namely,FollowPathandHighSpeedFollowPath. By default, the one defined in the Behavior tree is utilized. +In this case, theFollowPathis the default controller_id. The difference between the two controller_ids is that HighSpeedFollowPath has a higher max velocity compared to the FollowPath. This difference can be well noted in the GIF. + +## RPP new optionalinterpolate_curvature_after_goalbehavior and fix conflict betweenuse_rotate_to_headingandallow_reversing +In PR #4140a new optionalinterpolate_curvature_after_goalparameter (defaultfalse) was added that activates the interpolation of a carrot after the goal in order to maintain a constant curvature lookahead distance. This is to avoid instabilities at the end of the path on the generation of the angular speed. The carrot used for the linear speed computation stays the same. +Interpolation is based on the orientation of the vector formed by the last 2 poses of the path. Hence paths of length 1 are rejected wheninterpolate_curvature_after_goalistrue. It can be used only whenuse_fixed_curvature_lookahead:true. +Additionally, the conflict betweenuse_rotate_to_headingandallow_reversingwas fixed souse_rotate_to_headingcan now be used backward. + +## Cancel Checker Interface For GlobalPlanner +PR #4148introduces a new interface for theGlobalPlannerto allow for the cancellation of the current planning task. +Before the planners would continue to plan even if the goal was cancelled, now they can check it and stop planning if the goal is cancelled. +New interface forGlobalPlanner::createPlan: +This is implemented for all the planners in the stack, you can check them for the example use ofcancel_checkerfunction (simply checkcancel_checker()). +Smac and Theta* planners have a new parameterterminal_checking_intervalwhich is the frequency of the cancel or timeout checking in terms of number of iterations. + +## New BtActionServer/BtNavigator parameter +PR #4209introduces a new boolean parameteralways_reload_bt_xml, which enables the possibility to always reload a requested behavior tree XML description, regardless of the currently active XML. This allows keeping the action server running while changing/developing the XML description. + +## New collision monitor parameter +PR #4207introduces a new boolean parameterpolygon_subscribe_transient_local(value is false by default), which set the QoS durability for polygon topic or footprint topic subscription. + +## New graceful cancellation API for Controllers +PR #4136introduces a new graceful cancellation API for controllers. Previously when a goal was canceled, the controller would stop the robot immediately. This API allows the controller to stop the robot in a more graceful way. The new API is implemented in theRegulatedPurePursuitControllerby adding a new parametercancel_deceleration. So when the goal is canceled, a constant deceleration will be used while continuing to track the path to stop the robot instead of stopping immediately. This API can be should be added to all controllers that have acceleration limits. + +## Standardization of Plugin Naming with Double Colons (::) +`PR #4220`_standardizes plugin naming across the Navigation2 package to use double colons (::), replacing the previous mixed use of slashes (/) and double colons. Affected plugins include: + +## Collision monitor: dynamic radius for circle type polygons +PR #4226introduces usage of parameter.polygon_sub_topicfor circle type polygons. If parameter.radiusis not set, collision monitor node subscribes to topic.polygon_sub_topic(subscription type isstd_msgs/msg/Float32), and the current circle polygon radius will be updating accordingly to received messages on topic. + +## Static Layer: new parameterfootprint_clearing_enabled +PR #4282introduces usage of parameterfootprint_clearing_enabledfor the static layer. It works similarly to thefootprint_clearing_enabledparameter in the obstacle and voxel layer. If set totrue, the static layer will clear the costmap cells that are within the robot’s footprint. It isfalseby default to keep the previous behavior. + +## Lifecycle Node: added bond_heartbeat_period parameter (and allow disabling the bond mechanism) +PR #4342adds the parameterbond_heartbeat_periodto the lifecycle nodes to customize the bond mechanism publishing period (on the/bondtopic). Default value unchanged to 0.1s. Disabled if inferior or equal to 0.0. + +## Rotation Shim Controller: new parameterrotate_to_goal_heading +PR #4332introduces usage of parameterrotate_to_goal_headingfor the rotation shim controller. It allows the rotation shim controller to take back control when reaching the XY goal tolerance to perform a clean rotation towards the goal heading. Some controllers will do this internally, but it is a useful option for others. + +## MPPI Controller: Addition of acceleration constraints +PR #4352adds new parametersax_max,ax_min,ay_max,az_maxfor the MPPI controller. These parameters will enable the MPPI controller to generate local trajectories within the specified acceleration constraints. + +## RegulatedPurePursuit Controller [RPP]: new parameteruse_cancel_deceleration +PR #4441adds a new parameter use_cancel_deceleration for the regulated pure pursuit controllers. This parameter enables the controller to use a constant deceleration to stop the robot gracefully instead of stopping immediately when a goal is canceled. + +Code Examples: + +Language: unknown +File: "[[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],...]" +``` +PolygonFront +: +type +: +"polygon" +points +: +"[[0.3, +0.3], +[0.3, +-0.3], +[0.0, +-0.3], +[0.0, +0.3]]" +action_type +: +"none" +min_points +: +4 +visualize +: +True +polygon_pub_topic +: +"polygon_front" +``` + +Language: unknown +File: /etc/security/limits.conf +``` + soft rtprio 99 + hard rtprio 99 + +``` + +Language: unknown +File: ObstaclesCritic +``` +bt_navigator +: +ros__parameters +: +default_nav_to_pose_bt_xml +: +$(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml +``` + +Language: unknown +File: GlobalPlanner::createPlan +``` +virtual +nav_msgs +:: +msg +:: +Path +createPlan +( +const +geometry_msgs +:: +msg +:: +PoseStamped +& +start +, +const +geometry_msgs +:: +msg +:: +PoseStamped +& +goal +, +std +:: +function +< +bool +() +> +cancel_checker +) +``` diff --git "a/exported_docs/nav2/IsBatteryCharging\357\203\201.txt" "b/exported_docs/nav2/IsBatteryCharging\357\203\201.txt" new file mode 100644 index 0000000..d4c0307 --- /dev/null +++ "b/exported_docs/nav2/IsBatteryCharging\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: IsBatteryCharging +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsBatteryCharging.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: POWER_SUPPLY_STATUS_CHARGING +``` + +``` diff --git "a/exported_docs/nav2/IsBatteryLow\357\203\201.txt" "b/exported_docs/nav2/IsBatteryLow\357\203\201.txt" new file mode 100644 index 0000000..7b23d65 --- /dev/null +++ "b/exported_docs/nav2/IsBatteryLow\357\203\201.txt" @@ -0,0 +1,23 @@ +Title: IsBatteryLow +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsBatteryLow.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: is_voltage +``` + +``` diff --git "a/exported_docs/nav2/IsPathValid\357\203\201.txt" "b/exported_docs/nav2/IsPathValid\357\203\201.txt" new file mode 100644 index 0000000..7c7bbf0 --- /dev/null +++ "b/exported_docs/nav2/IsPathValid\357\203\201.txt" @@ -0,0 +1,21 @@ +Title: IsPathValid +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsPathValid.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/IsStopped\357\203\201.txt" "b/exported_docs/nav2/IsStopped\357\203\201.txt" new file mode 100644 index 0000000..e33c490 --- /dev/null +++ "b/exported_docs/nav2/IsStopped\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: IsStopped +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsStopped.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Port + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/IsStuck\357\203\201.txt" "b/exported_docs/nav2/IsStuck\357\203\201.txt" new file mode 100644 index 0000000..b102f98 --- /dev/null +++ "b/exported_docs/nav2/IsStuck\357\203\201.txt" @@ -0,0 +1,16 @@ +Title: IsStuck +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/IsStuck.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/Jazzy to K-Turtle\357\203\201.txt" "b/exported_docs/nav2/Jazzy to K-Turtle\357\203\201.txt" new file mode 100644 index 0000000..c987de3 --- /dev/null +++ "b/exported_docs/nav2/Jazzy to K-Turtle\357\203\201.txt" @@ -0,0 +1,185 @@ +Title: Jazzy to K-Turtle +URL: https://docs.nav2.org/migration/Jazzy.html#docking-with-static-infrastructure-or-dynamic-docking +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## TwistStamped Default CmdVel Change +In Kilted and newer, the defaultcmd_veltopic for allTwistpublishers and subscriptions is changed toTwistStampedin order to enable a broader range of applications. +it also allows for rejection of stale velocity messages, which can be useful in some applications. +Your robot should now subscribe to aTwistStampedmessage instead of aTwistmessage & update your simulation appropriately. +The topic names are the same. +However, this can be disabled by settingenable_twist_stampedtofalsein thenav2_params.yamlfile for all nodes that involve Twist subscriptions or publications. +See the configuration guide for more information on how to configure this parameter for each node. +An example simulation migration using Gazebo can be seen in thefollowing pull request for the Turtlebot 3 and 4. + +## New Nav2 Loopback Simulator +Thenav2_loopback_simis a stand-alone simulator to create a “loopback” for non-physical simulation to replace robot hardware, physics simulators (Gazebo, Bullet, Isaac Sim, etc). +It computes the robot’s odometry based on the command velocity’s output request to create a perfect ‘frictionless plane’-style simulation for unit testing, system testing, R&D on higher level systems, testing behaviors without concerning yourself with localization accuracy or system dynamics, and multirobot simulations. + +## Docking with Static Infrastructure or Dynamic Docking +InPR #4627a docking plugin type and logic was added to support non-charging dock types in the nav2 docking server. +This allows users to specify docking locations to static infrastructure, such as conveyers, or dynamic docking locations, such as a pallet. +It also includes a new docking plugin to demonstrate the new docking server capabilitiessimple_non_charging_dock. + +## New RViz panel for Docking +InPR #4458a new RViz panel was added to interact with the Docking Server. +This panel allows the user to: +The panel displays the action goal status and feedback published bynav2_msgs/DockRobotandnav2_msgs/UndockRobotactions. Users can find information such as elapsed time, number of retries and the current state of the action (staging, controlling, etc.), as well as the error codes of the action. +Here we can see the working demo of the plugin: + +## New BT Nodes +Below is a list of new BT Nodes added: + +## New RViz Tool for Costmap Cost Cell Inspection +InPR #4546a new RViz tool was added to get the costmap costcell’s cost and a service to get the costcell’s cost at the footprint pose. +Usage: +Working demo of the tool: + +## Fix flickering visualization +InPR #4561amap_vis_zparameter has been introduced to Costmap2DROS to help modify the map slightly below the default plane, aiming to eliminate rviz visualization flickering issues. +Default Value: +Minimum Value Without Flickering: +Before: +After: + +## Option to limit velocity through DWB trajectory +InPR #4663alimit_vel_cmd_in_trajparameter was introduced to DWB local planner to allow the user to limit the velocity used in the trajectory generation based on the robot’s current velocity. +Default value: + +## Option to disable zero velocity publishing on goal exit +InPR #4675apublish_zero_velocityparameter was introduced for theController serverin order to disable zero velocity publishing on goal exit. +Default value: + +## Added optional collision checking for the Docking Server +InPR #4752an optional collision checking feature was added to theDocking serverto check for collisions between the robot and the dock. +Default value: + +## Revamped multirobot bringup and config files to use namespaces +InPR #4715multirobot bringup and the use of namespaces were overhauled to be compatible out of the box with ROS namespaces and remove custom logic, specifically: +Note that some plugins / nodes might have their own local namespace. This is the case forCostmapLayerwhich will be in a/ns/[layer_name]namespace. For these, a new functionjoinWithParentNamespacehas been added to make sure joining relative paths results in/ns/topic_namerather than/ns/[layer_name]/topic_name. +If your use case doesn’t require multiple robots, keeping absolute paths in yournav2_params.yamlconfig file and rviz config file will preserve existing behavior. +For example, if you specifytopic:scanin thevoxel_layerof alocal_costmapand you launch your bringup with atb4namespace: + +## Removed global map_topic from Costmap node +InPR #4715the globalmap_topicparameter has been removed from theCostmap2DROSnode. This parameterwas only used in theStaticLayerand should be defined as a parameter local to theStaticLayerinstead, for example: + +## Simplified Costmap2DROS constructors +The following constructors forCostmap2DROShave been removed: +They have been consolidated into a single one: +Thelocal_namespaceparameter has been removed and is now automatically set to the node’s name (which is what the second removed constructor did). +Parametersparent_namespace/use_sim_timeboth provide default values to maintain the ability of creating aCostmap2DROSobject by just specifying a name. + +Code Examples: + +Language: unknown +File: StaticLayer +``` +global_costmap +: +global_costmap +: +ros__parameters +: +[ +... +] +# Not supported anymore +map_topic +: +my_map +static_layer +: +plugin +: +"nav2_costmap_2d::StaticLayer" +map_subscribe_transient_local +: +True +# Do this instead +map_topic +: +my_map +``` + +Language: unknown +File: Costmap2DROS +``` +explicit +Costmap2DROS +( +const +std +:: +string +& +name +, +const +std +:: +string +& +parent_namespace +, +const +std +:: +string +& +local_namespace +, +const +bool +& +use_sim_time +); +explicit +Costmap2DROS +( +const +std +:: +string +& +name +, +const +bool +& +use_sim_time += +false +); +``` + +Language: unknown +File: Costmap2DROS +``` +explicit +Costmap2DROS +( +const +std +:: +string +& +name +, +const +std +:: +string +& +parent_namespace += +"/" +, +const +bool +& +use_sim_time += +false +); +``` diff --git "a/exported_docs/nav2/Keepout Filter Parameters\357\203\201.txt" "b/exported_docs/nav2/Keepout Filter Parameters\357\203\201.txt" new file mode 100644 index 0000000..7b8dfe7 --- /dev/null +++ "b/exported_docs/nav2/Keepout Filter Parameters\357\203\201.txt" @@ -0,0 +1,86 @@ +Title: Keepout Filter Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/keepout_filter.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: +``` +global_costmap +: +global_costmap +: +ros__parameters +: +... +plugins +: +[ +"static_layer" +, +"obstacle_layer" +, +"inflation_layer" +] +filters +: +[ +"keepout_filter" +] +... +keepout_filter +: +plugin +: +"nav2_costmap_2d::KeepoutFilter" +enabled +: +True +filter_info_topic +: +"/costmap_filter_info" +transform_tolerance +: +0.1 +... +local_costmap +: +local_costmap +: +ros__parameters +: +... +plugins +: +[ +"voxel_layer" +, +"inflation_layer" +] +filters +: +[ +"keepout_filter" +] +... +keepout_filter +: +plugin +: +"nav2_costmap_2d::KeepoutFilter" +enabled +: +True +filter_info_topic +: +"/costmap_filter_info" +transform_tolerance +: +0.1 +``` diff --git "a/exported_docs/nav2/Kinematic Parameters\357\203\201.txt" "b/exported_docs/nav2/Kinematic Parameters\357\203\201.txt" new file mode 100644 index 0000000..62daa12 --- /dev/null +++ "b/exported_docs/nav2/Kinematic Parameters\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Kinematic Parameters +URL: https://docs.nav2.org/configuration/packages/dwb-params/kinematic.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. diff --git "a/exported_docs/nav2/Lifecycle Manager\357\203\201.txt" "b/exported_docs/nav2/Lifecycle Manager\357\203\201.txt" new file mode 100644 index 0000000..63754c5 --- /dev/null +++ "b/exported_docs/nav2/Lifecycle Manager\357\203\201.txt" @@ -0,0 +1,47 @@ +Title: Lifecycle Manager +URL: https://docs.nav2.org/configuration/packages/configuring-lifecycle.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: true +``` +lifecycle_manager +: +ros__parameters +: +autostart +: +true +node_names +: +[ +'controller_server' +, +'planner_server' +, +'behavior_server' +, +'bt_navigator' +, +'waypoint_follower' +] +bond_timeout +: +4.0 +attempt_respawn_reconnection +: +true +bond_respawn_max_duration +: +10.0 +``` diff --git "a/exported_docs/nav2/LimitedAccelGenerator\357\203\201.txt" "b/exported_docs/nav2/LimitedAccelGenerator\357\203\201.txt" new file mode 100644 index 0000000..665ed36 --- /dev/null +++ "b/exported_docs/nav2/LimitedAccelGenerator\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: LimitedAccelGenerator +URL: https://docs.nav2.org/configuration/packages/dwb-plugins/limited_accel_generator.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + diff --git "a/exported_docs/nav2/Loopback Simulator\357\203\201.txt" "b/exported_docs/nav2/Loopback Simulator\357\203\201.txt" new file mode 100644 index 0000000..31295de --- /dev/null +++ "b/exported_docs/nav2/Loopback Simulator\357\203\201.txt" @@ -0,0 +1,38 @@ +Title: Loopback Simulator +URL: https://docs.nav2.org/configuration/packages/configuring-loopback-sim.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: /clock +``` +loopback_simulator +: +ros__parameters +: +base_frame_id +: +"base_footprint" +odom_frame_id +: +"odom" +map_frame_id +: +"map" +scan_frame_id +: +"base_scan" +# tb4_loopback_simulator.launch.py remaps to 'rplidar_link' +update_duration +: +0.02 +``` diff --git "a/exported_docs/nav2/Map Server _ Saver\357\203\201.txt" "b/exported_docs/nav2/Map Server _ Saver\357\203\201.txt" new file mode 100644 index 0000000..08cc8f3 --- /dev/null +++ "b/exported_docs/nav2/Map Server _ Saver\357\203\201.txt" @@ -0,0 +1,69 @@ +Title: Map Server / Saver +URL: https://docs.nav2.org/configuration/packages/configuring-map-server.html#map-saver-parameters +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Map Saver Parameters + + +## Map Server Parameters + + +## Costmap Filter Info Server Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: filter_space_value=base+multiplier*mask_value +``` +map_server +: +ros__parameters +: +yaml_filename +: +"turtlebot3_world.yaml" +topic_name +: +"map" +frame_id +: +"map" +map_saver +: +ros__parameters +: +save_map_timeout +: +5.0 +free_thresh_default +: +0.25 +occupied_thresh_default +: +0.65 +costmap_filter_info_server +: +ros__parameters +: +type +: +1 +filter_info_topic +: +"costmap_filter_info" +mask_topic +: +"filter_mask" +base +: +0.0 +multiplier +: +0.25 +``` diff --git "a/exported_docs/nav2/Migration Guides\357\203\201.txt" "b/exported_docs/nav2/Migration Guides\357\203\201.txt" new file mode 100644 index 0000000..ce64fdf --- /dev/null +++ "b/exported_docs/nav2/Migration Guides\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Migration Guides +URL: https://docs.nav2.org/migration/index.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/Model Predictive Path Integral Controller\357\203\201.txt" "b/exported_docs/nav2/Model Predictive Path Integral Controller\357\203\201.txt" new file mode 100644 index 0000000..49c6f7a --- /dev/null +++ "b/exported_docs/nav2/Model Predictive Path Integral Controller\357\203\201.txt" @@ -0,0 +1,359 @@ +Title: Model Predictive Path Integral Controller +URL: https://docs.nav2.org/configuration/packages/configuring-mppic.html#path-align-critic +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## MPPI Parameters + + +## Trajectory Visualization + + +## Path Handler + + +## Ackermann Motion Model + + +## Constraint Critic +This critic penalizes trajectories that have components outside of the set dynamic or kinematic constraints + +## Goal Angle Critic +This critic incentivizes navigating to achieve the angle of the goal posewhen in reasonable proximity to goal + +## Goal Critic +This critic incentivizes navigating spatially towards the goal when in reasonable proximity to goal + +## Obstacles Critic +This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using distances from obstacles. + +## Cost Critic +This critic incentivizes navigating away from obstacles and critical collisions using either a circular robot point-check or full SE2 footprint check using the costmap values. + +## Path Align Critic +This critic incentivizes aligning with the global path, if relevant. It does not implement path following behavior. + +## Path Angle Critic +This critic penalizes trajectories at a high relative angle to the path. This helps the robot make sharp turns when necessary due to large accumulated angular errors. + +## Path Follow Critic +This critic incentivizes making progress along the path. This is what drives the robot forward along the path. + +## Prefer Forward Critic +This critic incentivizes moving in the forward direction, rather than reversing. + +## Twirling Critic +This critic penalizes unnecessary ‘twisting’ with holonomic vehicles. It adds a constraint on the rotation angle to keep it consistent. + +## Velocity Deadband Critic +This critic penalizes velocities that fall below the deadband threshold, helping to mitigate hardware limitations on certain platforms. + +## Example + + +## Notes to Users + + +## General Words of Wisdom +Themodel_dtparameter generally should be set to the duration of your control frequency. So if your control frequency is 20hz, this should be0.05. However, you may also set it lowerbut not larger. +Visualization of the trajectories usingvisualizeuses compute resources to back out trajectories for visualization and therefore slows compute time. It is not suggested that this parameter is set totrueduring a deployed use, but is a useful debug instrument while tuning the system, but use sparingly. Visualizing 2000 batches @ 56 points at 30 hz isa lot. +The most common parameters you might want to start off changing are the velocity profiles (vx_max,vx_min,wz_max, andvy_maxif holonomic) and themotion_modelto correspond to your vehicle. Its wise to consider theprune_distanceof the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics’repulsion_weightsince the tuning of this is proprtional to your inflation layer’s radius. Higher radii should correspond to reducedrepulsion_weightdue to the penalty formation (e.g.inflation_radius-min_dist_to_obstacle). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information ifconsider_footprint=true, though comes at an increased compute cost. +Otherwise, the parameters have been closely pre-tuned by your friendly neighborhood navigator to give you a decent starting point that hopefully you only need to retune for your specific desired behavior lightly (if at all). Varying costmap parameters or maximum speeds are the actions which require the most attention, as described below: + +## Prediction Horizon, Costmap Sizing, and Offsets +As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps*model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artificially limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, theminimumrequired costmap radius is 1.5m - or 3m total width. +The same applies to the Path Follow and Align offsets from furthest. In the same example if the furthest point we can consider is already at the edge of the costmap, then further offsets are thresholded because they’re unusable. So its important while selecting these parameters to make sure that the theoretical offsets can exist on the costmap settings selected with the maximum prediction horizon and velocities desired. Setting the threshold for consideration in the path follower + goal critics as the same as your prediction horizon can make sure you have clean hand-offs between them, as the path follower will otherwise attempt to slow slightly once it reaches the final goal pose as its marker. +The Path Follow critic cannot drive velocities greater than the projectable distance of that velocity on the available path on the rolling costmap. The Path Align criticoffset_from_furthestrepresents the number of path points a trajectory passes through while tracking the path. If this is set either absurdly low (e.g. 5) it can trigger when a robot is simply trying to start path tracking causing some suboptimal behaviors and local minima while starting a task. If it is set absurdly high (e.g. 50) relative to the path resolution and costmap size, then the critic may never trigger or only do so when at full-speed. A balance here is wise. A selection of this value to be ~30% of the maximum velocity distance projected is good (e.g. if a planner produces points every 2.5cm, 60 can fit on the 1.5m local costmap radius. If the max speed is 0.5m/s with a 3s prediction time, then 20 points represents 33% of the maximum speed projected over the prediction horizon onto the path). When in doubt,prediction_horizon_s*max_speed/path_resolution/3.0is a good baseline. + +## Obstacle, Inflation Layer, and Path Following +There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvers when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task. +Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn’t overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered. +As you increase or decrease your weights on the Obstacle, you may notice the aforementioned behaviors (e.g. won’t overcome free to non-free threshold). To overcome them, increase the FollowPath critic cost to increase the desire for the trajectory planner to continue moving towards the goal. Make sure to not overshoot this though, keep them balanced. A desirable outcome is smooth motion roughly in the center of spaces without significant close interactions with obstacles. It shouldn’t be perfectly following a path yet nor should the output velocity be wobbling jaggedly. +Once you have your obstacle avoidance behavior tuned and matched with an appropriate path following penalty, tune the Path Align critic to align with the path. If you design exact-path-alignment behavior, its possible to skip the obstacle critic step as highly tuning the system to follow the path will give it less ability to deviate to avoid obstacles (though it’ll slow and stop). Tuning the critic weight for the Obstacle critic high will do the job to avoid near-collisions but the repulsion weight is largely unnecessary to you. For others wanting more dynamic behavior, itcanbe beneficial to slowly lower the weight on the obstacle critic to give the path alignment critic some more room to work. If your path was generated with a cost-aware planner (like all provided by Nav2) and providing paths sufficiently far from obstacles for your satisfaction, the impact of a slightly reduced Obstacle critic with a Path Alignment critic will do you well. Not over-weighting the path align critic will allow the robot to deviate from the path to get around dynamic obstacles in the scene or other obstacles not previous considered during path planning. It is subjective as to the best behavior for your application, but it has been shown that MPPI can be an exact path tracker and/or avoid dynamic obstacles very fluidly and everywhere in between. The defaults provided are in the generally right regime for a balanced initial trade-off. + +Code Examples: + +Language: unknown +File: inflation_radius +``` +controller_server +: +ros__parameters +: +controller_frequency +: +30.0 +FollowPath +: +plugin +: +"nav2_mppi_controller::MPPIController" +time_steps +: +56 +model_dt +: +0.05 +batch_size +: +2000 +vx_std +: +0.2 +vy_std +: +0.2 +wz_std +: +0.4 +vx_max +: +0.5 +vx_min +: +-0.35 +vy_max +: +0.5 +wz_max +: +1.9 +ax_max +: +3.0 +ax_min +: +-3.0 +ay_max +: +3.0 +az_max +: +3.5 +iteration_count +: +1 +prune_distance +: +1.7 +transform_tolerance +: +0.1 +temperature +: +0.3 +gamma +: +0.015 +motion_model +: +"DiffDrive" +visualize +: +false +reset_period +: +1.0 +# (only in Humble) +regenerate_noises +: +false +TrajectoryVisualizer +: +trajectory_step +: +5 +time_step +: +3 +AckermannConstraints +: +min_turning_r +: +0.2 +critics +: +[ +"ConstraintCritic" +, +"CostCritic" +, +"GoalCritic" +, +"GoalAngleCritic" +, +"PathAlignCritic" +, +"PathFollowCritic" +, +"PathAngleCritic" +, +"PreferForwardCritic" +] +ConstraintCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +4.0 +GoalCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +5.0 +threshold_to_consider +: +1.4 +GoalAngleCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +3.0 +threshold_to_consider +: +0.5 +PreferForwardCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +5.0 +threshold_to_consider +: +0.5 +# ObstaclesCritic: +# enabled: true +# cost_power: 1 +# repulsion_weight: 1.5 +# critical_weight: 20.0 +# consider_footprint: false +# collision_cost: 10000.0 +# collision_margin_distance: 0.1 +# near_goal_distance: 0.5 +# inflation_radius: 0.55 # (only in Humble) +# cost_scaling_factor: 10.0 # (only in Humble) +CostCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +3.81 +critical_cost +: +300.0 +consider_footprint +: +true +collision_cost +: +1000000.0 +near_goal_distance +: +1.0 +trajectory_point_step +: +2 +PathAlignCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +14.0 +max_path_occupancy_ratio +: +0.05 +trajectory_point_step +: +4 +threshold_to_consider +: +0.5 +offset_from_furthest +: +20 +use_path_orientations +: +false +PathFollowCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +5.0 +offset_from_furthest +: +5 +threshold_to_consider +: +1.4 +PathAngleCritic +: +enabled +: +true +cost_power +: +1 +cost_weight +: +2.0 +offset_from_furthest +: +4 +threshold_to_consider +: +0.5 +max_angle_to_furthest +: +1.0 +mode +: +0 +# VelocityDeadbandCritic: +# enabled: true +# cost_power: 1 +# cost_weight: 35.0 +# deadband_velocities: [0.05, 0.05, 0.05] +# TwirlingCritic: +# enabled: true +# twirling_cost_power: 1 +# twirling_cost_weight: 10.0 +``` diff --git "a/exported_docs/nav2/Nav2 Behavior Trees\357\203\201.txt" "b/exported_docs/nav2/Nav2 Behavior Trees\357\203\201.txt" new file mode 100644 index 0000000..cd7c9aa --- /dev/null +++ "b/exported_docs/nav2/Nav2 Behavior Trees\357\203\201.txt" @@ -0,0 +1,42 @@ +Title: Nav2 Behavior Trees +URL: https://docs.nav2.org/behavior_trees/index.html +Section: behavior_trees/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: nav2_bt_navigator +``` + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Nav2\357\203\201.txt" "b/exported_docs/nav2/Nav2\357\203\201.txt" new file mode 100644 index 0000000..121f099 --- /dev/null +++ "b/exported_docs/nav2/Nav2\357\203\201.txt" @@ -0,0 +1,346 @@ +Title: Nav2 +URL: https://docs.nav2.org/index.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Our Sponsors + + +## Services +If you need professional services related to Nav2, please contact Open Navigation atinfo@opennav.org. + +## Overview +Nav2 is the professionally-supported successor of the ROS Navigation Stack deploying the same kinds of technology powering Autonomous Vehicles brought down, optimized, and reworked for mobile and surface robotics. +This project allows for mobile robots to navigate through complex environments to complete user-defined application tasks with nearly any class of robot kinematics. +Not only can it move from Point A to Point B, but it can have intermediary poses, and represent other types of tasks like object following, complete coverage navigation, and more. +Nav2 is a production-grade and high-quality navigation framework trusted by 100+ companies worldwide. +It provides perception, planning, control, localization, visualization, and much more to build highly reliable autonomous systems. +This will compute an environmental model from sensor and semantic data, dynamically path plan, compute velocities for motors, avoid obstacles, and structure higher-level robot behaviors. +To learn more about this project, such as related projects, robots using, ROS1 comparison, and maintainers, seeAbout and Contact. +To learn more about navigation and ROS concepts, seeNavigation Concepts. +Nav2 uses behavior trees to create customized and intelligent navigation behavior via orchestrating many independent modular servers. +A task server can be used to compute a path, control effort, behavior, or any other navigation +related task. These separate servers communicate with the behavior tree (BT) +over a ROS interface such as an action server or service. +A robot may utilize potentially many different behavior trees to allow a robot to perform many types of unique and complex tasks. +The diagram below will give you a good first-look at the structure of Nav2. +Note that it is possible to have multiple plugins for controllers, planners, +and recoveries in each of their servers. This can be used to create contextual navigation behaviors. +Each of the servers also returns status indicators back to the BT Navigator in order to enact contextual behaviors based on their results. +The expected inputs to Nav2 are TF transformations conforming to REP-105, a +map source if utilizing the Static Costmap Layer, a BT XML file, and any relevant sensor data +sources. It will then provide valid velocity commands for the motors of a holonomic or +non-holonomic robot to follow when properly configured. We currently support all of the major robot types: +holonomic, differential-drive, legged, and ackermann (car-like) base types! We support +them uniquely with both circular and arbitrarily-shaped robots for SE2 collision checking. +It has tools to: +We also provide a set of starting plugins to get you going. +A list of all plugins can be found onNavigation Plugins- but they include algorithms for the spanning cross section of common behaviors and robot platform types. + +## Related Projects +Check out related projects to Nav2: + +## Citations +If you use the navigation framework, an algorithm from this repository, or ideas from it +please cite this work in your papers! +S. Macenski, F. Martín, R. White, J. Clavero.The Marathon 2: A Navigation System. +IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2020. +IROS 2020 talk on Nav2 Marathon Experiments: +If you use any of the algorithms in Nav2 or the analysis of the algorithms in your work, please cite this work in your papers! +S. Macenski, T. Moore, DV Lu, A. Merzlyakov, M. Ferguson,From the desks of ROS maintainers: A survey of modern & capable mobile robotics algorithms in the robot operating system 2, +Robotics and Autonomous Systems, 2023 +Smac Planner (Hybrid A*, State Lattice, 2D): +S. Macenski, M. Booker, J. Wallace,Open-Source, Cost-Aware Kinematically Feasible Planning for Mobile and Surface Robotics, +Regulated Pure Pursuit Controller: +S. Macenski, S. Singh, F. Martin, J. Gines,Regulated Pure Pursuit for Robot Path Tracking, +Autonomous Robots, 2023. +VSLAM and formal comparisons for service robot needs: +A. Merzlyakov, S. Macenski.A Comparison of Modern General-Purpose Visual SLAM Approaches. +IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2021. + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +@InProceedings +{ +macenski2020marathon2, + +author += +{ +Macenski, +Steven +and +Martin, +Francisco +and +White, +Ruffin +and +Ginés +Clavero, +Jonatan +} +, + +title += +{ +The +Marathon +2 +: +A +Navigation +System +} +, + +booktitle += +{ +2020 +IEEE/RSJ +International +Conference +on +Intelligent +Robots +and +Systems +( +IROS +)} +, + +year += +{ +2020 +} +} +``` + +Language: unknown +File: use_cancel_deceleration +``` +@article +{ +macenski2023survey, + +title +={ +From +the +desks +of +ROS +maintainers: +A +survey +of +modern +& +capable +mobile +robotics +algorithms +in +the +robot +operating +system +2 +} +, + +author +={ +S. +Macenski, +T. +Moore, +DV +Lu, +A. +Merzlyakov, +M. +Ferguson +} +, + +year +={ +2023 +} +, + +journal += +{ +Robotics +and +Autonomous +Systems +} +} +``` + +Language: unknown +File: use_cancel_deceleration +``` +@article +{ +macenski2024smac, + +title +={ +Open-Source, +Cost-Aware +Kinematically +Feasible +Planning +for +Mobile +and +Surface +Robotics +} +, + +author +={ +Steve +Macenski +and +Matthew +Booker +and +Josh +Wallace +} +, + +year +={ +2024 +} +, + +journal += +{ +Arxiv +} +} +``` + +Language: unknown +File: use_cancel_deceleration +``` +@article +{ +macenski2023regulated, + +title +={ +Regulated +Pure +Pursuit +for +Robot +Path +Tracking +} +, + +author +={ +Steve +Macenski +and +Shrijit +Singh +and +Francisco +Martin +and +Jonatan +Gines +} +, + +year +={ +2023 +} +, + +journal += +{ +Autonomous +Robots +} +} +``` + +Language: unknown +File: use_cancel_deceleration +``` +@InProceedings +{ +vslamComparison2021, + +author += +{ +Merzlyakov, +Alexey +and +Macenski, +Steven +} +, + +title += +{ +A +Comparison +of +Modern +General-Purpose +Visual +SLAM +Approaches +} +, + +booktitle += +{ +2021 +IEEE/RSJ +International +Conference +on +Intelligent +Robots +and +Systems +( +IROS +)} +, + +year += +{ +2021 +} +} +``` diff --git "a/exported_docs/nav2/NavFn Planner\357\203\201.txt" "b/exported_docs/nav2/NavFn Planner\357\203\201.txt" new file mode 100644 index 0000000..dc1c936 --- /dev/null +++ "b/exported_docs/nav2/NavFn Planner\357\203\201.txt" @@ -0,0 +1,42 @@ +Title: NavFn Planner +URL: https://docs.nav2.org/configuration/packages/configuring-navfn.html#parameters +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: +``` +planner_server +: +ros__parameters +: +planner_plugins +: +[ +'GridBased' +] +GridBased +: +plugin +: +'nav2_navfn_planner::NavfnPlanner' +# In Iron and older versions, "/" was used instead of "::" +use_astar +: +True +allow_unknown +: +True +tolerance +: +1.0 +``` diff --git "a/exported_docs/nav2/Navigate Through Poses\357\203\201.txt" "b/exported_docs/nav2/Navigate Through Poses\357\203\201.txt" new file mode 100644 index 0000000..0fbd73d --- /dev/null +++ "b/exported_docs/nav2/Navigate Through Poses\357\203\201.txt" @@ -0,0 +1,179 @@ +Title: Navigate Through Poses +URL: https://docs.nav2.org/behavior_trees/trees/nav_through_poses_recovery.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: FollowPath +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Navigate To Pose With Consistent Replanning And If Path Becomes Invalid\357\203\201.txt" "b/exported_docs/nav2/Navigate To Pose With Consistent Replanning And If Path Becomes Invalid\357\203\201.txt" new file mode 100644 index 0000000..e6b67d4 --- /dev/null +++ "b/exported_docs/nav2/Navigate To Pose With Consistent Replanning And If Path Becomes Invalid\357\203\201.txt" @@ -0,0 +1,163 @@ +Title: Navigate To Pose With Consistent Replanning And If Path Becomes Invalid +URL: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_with_consistent_replanning_and_if_path_becomes_invalid.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: FollowPath +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Navigate To Pose and Pause Near Goal-Obstacle\357\203\201.txt" "b/exported_docs/nav2/Navigate To Pose and Pause Near Goal-Obstacle\357\203\201.txt" new file mode 100644 index 0000000..6e0be80 --- /dev/null +++ "b/exported_docs/nav2/Navigate To Pose and Pause Near Goal-Obstacle\357\203\201.txt" @@ -0,0 +1,173 @@ +Title: Navigate To Pose and Pause Near Goal-Obstacle +URL: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_and_pause_near_goal_obstacle.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: FollowPath +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Navigate To Pose\357\203\201.txt" "b/exported_docs/nav2/Navigate To Pose\357\203\201.txt" new file mode 100644 index 0000000..cf20815 --- /dev/null +++ "b/exported_docs/nav2/Navigate To Pose\357\203\201.txt" @@ -0,0 +1,169 @@ +Title: Navigate To Pose +URL: https://docs.nav2.org/behavior_trees/trees/nav_to_pose_recovery.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: FollowPath +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/NavigateThroughPoses\357\203\201.txt" "b/exported_docs/nav2/NavigateThroughPoses\357\203\201.txt" new file mode 100644 index 0000000..0a39971 --- /dev/null +++ "b/exported_docs/nav2/NavigateThroughPoses\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: NavigateThroughPoses +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/NavigateThroughPoses.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +/behavior_trees/navigate_through_poses_w_replanning_and_recovery.xml" +/> +``` diff --git "a/exported_docs/nav2/NavigateToPose\357\203\201.txt" "b/exported_docs/nav2/NavigateToPose\357\203\201.txt" new file mode 100644 index 0000000..a62b003 --- /dev/null +++ "b/exported_docs/nav2/NavigateToPose\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: NavigateToPose +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/NavigateToPose.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +/behavior_trees/navigate_through_poses_w_replanning_and_recovery.xml" +/> +``` diff --git "a/exported_docs/nav2/Navigating Using GPS Localization\357\203\201.txt" "b/exported_docs/nav2/Navigating Using GPS Localization\357\203\201.txt" new file mode 100644 index 0000000..a61a10b --- /dev/null +++ "b/exported_docs/nav2/Navigating Using GPS Localization\357\203\201.txt" @@ -0,0 +1,614 @@ +Title: Navigating Using GPS Localization +URL: https://docs.nav2.org/tutorials/docs/navigation2_with_gps.html#interactive-gps-waypoint-follower +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to set up a localization system using a GPS sensor(s) as the source of global positioning, robot_localization (RL) for sensor fusion, and how to use Nav2 to follow GPS waypoints. It was written by Pedro Gonzalez atKiwibot. + +## Requirements +It is assumed ROS2 and Nav2 dependent packages are installed or built locally. Additionally you will have to install robot_localization and mapviz: +The code for this tutorial is hosted onnav2_gps_waypoint_follower_demo. Though we will go through the most important steps of the setup, it’s highly recommended that you clone and build the package when setting up your dev environment. +This is available in ROS 2 Iron and newer. +You may also need to install gazebo and turtlebot3 simulation if you have not executed previous tutorials or Nav2 demos. See Nav2’s Getting Started page for more information. + +## GPS Localization Overview +GPS (Global Positioning System) or more broadly GNSS (Global Navigation Satellite System) is a technology that relies on satellites to provide receivers with an estimate of where they are located on the earth. These satellites are in orbit at altitudes around 20.000km and use radio frequency to continuously broadcast time signals, these are picked up by receivers when satellites are along their line of sight, they use trilateration to estimate their latitude, longitude and altitude. +Commonly GPS devices calculate their position using theWGS84 standard, which defines a cartesian system with its origin on the earth’s center of mass, thezaxis pointing north and thexaxis pointing to the first meridian as the image below shows. +However, this reference system is impractical for describing the motion and representing the environment around objects in or close to the earth’s surface: Imagine your robot is located on a soccer field and you want it to move from one end to the other, your navigation task would look something like: +Addinally, if your robot has for instance a 2D lidar, you would have to transform its data to this reference system as well. It would make much more sense to create a local reference system where you could tell your robot “go 100 meters forward” and your sensor data could populate your environment representation accordingly, right? +To cope with this, geodesy proposes several planar projection systems for localization with respect to the surface of the earth. One of them is theUTM coordinate system, which assumes earth is an ellipsoid and divides it in 60 zones, each of them spanning across 6 longitude degrees. A zone represents the projection of the ellipsoid’s surface over a secant cylinder parallel to its central meridian; each of them is then split into 20 latitude bands that span across 8 latitude degrees, which create local grid zones where positions are expressed using planar coordinates from the origin of the zone. The image below shows the grid zones spanning across South America. +robot_localizationuses this projection system to transform GPS measurements in the WGS84 reference system to a cartesian system, which centered on the origin of the grid zone where the GPS is at. This is achieved through thenavsat_transform node. This node complies with the ENU convention inREP 103, meaning that the+xaxis of theutmcoordinate system faces east, the+yfaces north and the+zaxis points up. +In the real world GPS sensors can be noisy: With standalone GPSs you should expect accuracies of 1-2 meters under excellent conditions and up to 10 meters, and frequent jumps in the position as the GPS sensor picks up less or more satellites, which can degrade the quality of navigation significantly. Several positioning augmentation technologies exists to reduce the error of GPS measurements, one of the most common ones is calledRTK(Real Time Kinematic Positioning), which can bring the accuracy of receivers down to 1cm. If accuracy matters in your application this technology is highly recommended; though this requires the deployment of a second fixed GPS called base, most of the US and Europe are already covered with public free to use bases that you can connect to. You can read more about RTK and how to get startedhere. In this tutorial we assume the robot’s GPS produces an accurate and smooth estimation of the robot’s position. +Additionally, to fully describe a robot’s localization we need to know its heading as well, however standalone GPS sensors do not provide orientation measurements, only position measurements. In this tutorial we will refer to ‘absolute heading’ as a yaw measurement which is given w.r.t. a cardinal direction (e.g, the east), in contrast to relative heading, which is given w.r.t. the angle the robot is turned on or any other reference that cannot be directly mapped to a cardinal direction. +When using robot_localization with GPS, measuring absolute orientation is mandatory. There are several strategies for getting absolute orientation data, like IMUs with magnetometers, dual GPS systems or matching techniques over a known map; in this tutorial we assume the robot is equipped with an IMU that can accurately measure absolute orientation following the ENU convention, meaning it will output zero yaw when facing east and +90 degrees when facing north. +Despite the above assumption, in the real world commercial grade IMU’s mounted in actual robots will often not produce accurate absolute heading measurements because: +Thus, for a particular application you should consider the behavior and localization quality you require when making decisions about how to estimate your absolute heading. When using IMU’s without relative headings to a cardinal direction, the robot may need to move around for a bit in an ‘initialization dance’ to converge to the right heading using the filter. Using dual-GPS or 3D mapping system overlay, the initial heading is quite good. +For the purposes of this tutorial, we model a well-built system using an IMU that has absolute orientation already, but that may be augmented or replaced on a practical system using one of the techniques above (or others). + +## Tutorial Steps + + +## 0- Setup Gazebo World +To navigate using GPS we first need to create an outdoors Gazebo world with a robot having a GPS sensor to setup for navigation. For this tutorial we will be using theSonoma Racewaybecause its aligned with the real location. A sample world has been setuphereusing gazebo’s spherical coordinates plugin, which creates a local tangent plane centered in the set geographic origin and provides latitude, longitude and altitude coordinates for each point in the world: +To get GPS readings from Gazebo we need to create a robot model with a GPS sensor. An updated Turtlebot model with such sensor is provided in thetutorial repo, it outputsNavSatFixmessages on the topic/gps/fix: +Additionally, since we added a new GPS sensor in thegps_linkwe need to add a joint for this link that publishes a static transform w.r.t.base_link +Build thenav2_gps_waypoint_follower_demopackage, source your workspace and test your gazebo world is properly set up by launching: +A Turtlebot waffle should appear in the Sonoma Raceway world. You may also echo the topic/gps/fixto verify the robot is indeed producing GPS measurements + +## 1- Setup GPS Localization system +Once you have your simulation (or real robot) up and running, it’s time to set up your localization system. Remember that Nav2 uses atfchain with the structuremap->odom->base_link->[sensorframes]; global localization (map->odom) is usually provided byamcl, whileodom->base_linkis usually provided by the user’s odometry system (wheel odometry, visual odometry, etc). +In this tutorial, the GPS sensor on the robot will replaceamclin providing global localization. Though you may build a custom module that takes in theNavSatFixandImumessages of your GPS and imu, and outputs atfbetween yourmapandodomframes using a planar projection, Nav2’s GPS waypoint follower currently uses robot_localization for converting GPS goals to cartesian goals, and thus at anavsat_transform_nodeshould be active. Additionally,robot_localizationfeatures reconfigurable state estimation nodes that use Kalman Filters to fuse multiple sources of data, which is yet another reason to use it. +We will setup one Extended Kalman Filter for local odometry, fusing wheel odometry and IMU data; a second one for global localization, fusing the local cartesian converted GPS coordinates, the wheel odometry and the IMU data; and a navsat_transform node to output cartesian odometry messages from GPS data. This is a common setup on robot_localization when using GPS data and more details around its configuration can be found inRL’s docs. +Aconfiguration fileand alaunch fileare provided for this purpose. You may take a while before continuing to understand these two files and what they configure. Let’s walk through the most relevant setting of each node. + +## Local Odometry +The local odometry is provided by theekf_filter_node_odom, which publishes the transform betweenodomandbase_footprint, the base frame of the turtlebot’s diff drive plugin in gazebo. The robot state publisher provides a static transform betweenbase_footprintandbase_link, however make sure to set the base frame properly in RL according to your configuration. Note that the EKFs are set to work in 2D mode, this is because nav2’s costmap environment representation is 2-Dimensional, and several layers rely on thebase_linkframe being on the same plane as their global frame for the height related parameters to make sense. This is encoded in the following parameters: +Since perREP 105the position of the robot in theodomframe has to be continuous over time, in this filter we just want to fuse the robot’s speed measured by its wheels published/odom, and the imu heading published on/imu: + +## Global Odometry +The global odometry is provided by theekf_filter_node_map, which publishes the transform betweenmapandbase_footprint. This EKF is set to work in 2D mode as well. In addition to the IMU and wheel odometry data, this filter takes in the odometry output of the gps, published by thenavsat_transformnode on/odometry/gpsas an odometry message: + +## Navsat Transform +The navsat transform produces an odometry output with the position of the GPS in themapframe, which is ingested by the global EKF as said above. It exposes thedatumparameter to set the GPS coordinates and heading of the origin ofmap; if left undeclared it will be set automatically to the coordinates of the first validNavSatFixmessage it gets, and it may be changed in runtime as well calling the/datumservice. +In this tutorial we will go with the automaticdatuminitialization because there is no information about the environment stored in cartesian coordinates (a static map, semantic navigation waypoints, a 3D pointcloud map, etc), however if that’s the case in your application you may fix thedatumso a given pair of coordinates produced by the GPS always correspond to the same cartesian coordinates in your reference system. +The node also exposes theyaw_offsetparameter to compensate for known errors that the IMU absolute yaw measurement may have with respect to the east. Since Gazebo’s IMU follows the ENU convention this is set to0in the tutorial, but you may want to change it if you know beforehand there’s a fixed offset in your data. +Here’s the full configuration for thenavsat_transformnode: + +## Localization Testing +As a sanity check that everything is working correctly, launch RL’s launch file while Gazebo is still running: +On a different terminal launch mapviz using the pre-builtconfig filein the repo.Get a bing maps API keyand use it to display satellite pictures. +You should see the window below after properly setting the API key: +Finally run the teleop twist keyboard node to teleoperate the simulated Turtlebot: +When you have everything up and running, start teleoperating the Turtlebot and check that: +The gif below shows what you should see: +Sensors in a real robot may be less accurate than Gazebo’s, especially GPSs and absolute heading measurements from IMUs. To mitigate this you can leverage robot_localization’s EKFs to complement sensor’s capabilities: + +## 2- Setup Navigation system +Once you have your localization system up and running it’s time to set up Nav2. Since RL is already providing thetftree we don’t need to launchamcl, thus we can remove its parameters from the params file and not launch Nav2’s localization launch file. +There are three main possible setups for the global costmap: +We provide aNav2 params filewith the rolling costmap setup and alaunch fileto put it all together. Remember that the GPS setup of robot_localization was just a means for setting up the global localization system, however Nav2 is still a cartesian navigation stack and you may still use all its cartesian tools. To confirm that everything is working, launch the provided file (this launches gazebo and RL as well so close them if you have them running from the previous steps) and use rviz to send a goal to the robot: +The gif below shows what you should see Nav2 navigating the robot autonomously! + +## 3- Interactive GPS Waypoint Follower +Now that we have performed our complete system setup, let’s leverage Nav2 GPS waypoint follower capabilities to navigate to goals that are expressed directly in GPS coordinates. For this demo we want to build an interactive interface similar to rviz’s, that allows us to click over a map to make the robot navigate to the clicked location. For that we will use mapviz’s point click publisher on thewgs84reference frame, which will publish aPointStampedmessage with the GPS coordinates of the point clicked over the satellite image. This is a great way to get started in your custom GPS navigation setup! +For this purpose we provide theinteractive_waypoint_followerpython node, which subscribes to mapviz’s topic and calls the/follow_gps_waypointsaction server with the clicked point as goal using theBasicNavigatorinnav2_simple_commander. To run it source your workspace and with the rest of the system running type: +You can now click on the mapviz map the pose you want the robot to go. The gif below shows the robot navigating to the finish line going through some obstacles: + +## 4- Logged GPS Waypoint Follower & Waypoint Logging +Finally let’s make a robot go through a set of predefined GPS waypoints. We provide awaypoint logging toolthat subscribes to the robot’s GPS and IMU and offers a simple GUI to save the robot coordinates and heading on demand to ayamlfile with the format: +Let’s log some waypoints for the robot to follow. Source your workspace and with the rest of the system running type: +If you don’t provide a path to save your waypoints, they will be saved in yourhomefolder by default with the namegps_waypoints.yaml. Once the node launches you should see a small GUI with a button to log waypoints, you may now move the robot around and click that button to record its position as the gif below shows: +After that you should get ayamlfile in the location you specified with the format shown above; let’s now make the robot follow the logged waypoints. For this purpose we provide thelogged_waypoint_followernode, which takes in the path to the waypoints file as an argument and uses theBasicNavigatorinnav2_simple_commanderto send the logged goals to the/follow_gps_waypointsaction server. If not provided, the node uses thedefault waypointsin thenav2_gps_waypoint_follower_demopackage. +To run this node source your workspace and with the rest of the system running type: +You should now see the robot following the waypoints you previously logged: + +## Conclusion +This tutorial discussed the usage of a GPS sensor for global localization using RL and thenavsat_transformnode, covering the setup of a gazebo simulation with a GPS equipped robot as well. It also went through the configuration changes in Nav2 for navigating with GPS localization, emphasizing on some different possibilities for setting up the global costmap. Finally it showcased the capabilities of Nav2’s GPS waypoint follower as a demonstration on how to use the stack in outdoors environments. +The tutorial should be a good starting point for setting up autonomous navigation using Nav2 on an outdoors robot, however users should keep in mind that GPS is just a means for providing global localization to the stack, and that all cartesian tools in Nav2 are still available for going past the GPS waypoint follower and building custom autonomy applications according to each use case. +Happy outdoors navigating! + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +source +/opt/ros//setup.bash +sudo +apt +install +ros- +$ROS_DISTRO +-robot-localization +sudo +apt +install +ros- +$ROS_DISTRO +-mapviz +sudo +apt +install +ros- +$ROS_DISTRO +-mapviz-plugins +sudo +apt +install +ros- +$ROS_DISTRO +-tile-map + +``` + +Language: unknown +File: +z +``` + + + +EARTH_WGS84 + + +38.161479 + + +-122.454630 + + +488.0 + + +180 + + +``` + +Language: unknown +File: /gps/fix +``` + + +true + + +1 + + +0 +0 +0 +0 +0 +0 + + + + + + +0.0 + + +0.01 + + + + + + +0.0 + + +0.01 + + + + + + + + +~/out:=/gps/fix + + + + +``` + +Language: unknown +File: base_link +``` + + + + + +``` + +Language: unknown +File: nav2_gps_waypoint_follower_demo +``` +ros2 +launch +nav2_gps_waypoint_follower_demo +gazebo_gps_world.launch.py + +``` + +Language: unknown +File: base_link +``` +ekf_filter_node_odom +: +ros__parameters +: +two_d_mode +: +true +publish_tf +: +true +base_link_frame +: +base_footprint +world_frame +: +odom +``` + +Language: unknown +File: /imu +``` +odom0 +: +odom +odom0_config +: +[ +false +, +false +, +false +, +false +, +false +, +false +, +true +, +true +, +true +, +false +, +false +, +true +, +false +, +false +, +false +] +imu0 +: +imu +imu0_config +: +[ +false +, +false +, +false +, +false +, +false +, +true +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +] +``` + +Language: unknown +File: /odometry/gps +``` +ekf_filter_node_map +: +ros__parameters +: +two_d_mode +: +true +publish_tf +: +true +base_link_frame +: +base_footprint +world_frame +: +map +odom1 +: +odometry/gps +odom1_config +: +[ +true +, +true +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +] +``` + +Language: unknown +File: navsat_transform +``` +navsat_transform +: +ros__parameters +: +frequency +: +30.0 +delay +: +3.0 +magnetic_declination_radians +: +0.0 +yaw_offset +: +0.0 +zero_altitude +: +true +broadcast_utm_transform +: +true +publish_filtered_gps +: +true +use_odometry_yaw +: +true +wait_for_datum +: +false +# datum: [38.161491, -122.4546443, 0.0] # pre-set datum if needed, [lat, lon, yaw] +``` + +Language: unknown +File: navsat_transform +``` +ros2 +launch +nav2_gps_waypoint_follower_demo +dual_ekf_navsat.launch.py + +``` + +Language: unknown +File: navsat_transform +``` +ros2 +launch +nav2_gps_waypoint_follower_demo +mapviz.launch.py + +``` + +Language: unknown +File: navsat_transform +``` +ros2 +run +teleop_twist_keyboard +teleop_twist_keyboard + +``` + +Language: unknown +File: datum +``` +global_costmap +: +global_costmap +: +ros__parameters +: +... +rolling_window +: +True +width +: +50 +height +: +50 +``` + +Language: unknown +File: datum +``` +global_costmap +: +global_costmap +: +ros__parameters +: +... +plugins +: +[ +"static_layer" +, +"obstacle_layer" +, +"inflation_layer" +] +``` + +Language: unknown +File: datum +``` +global_costmap +: +global_costmap +: +ros__parameters +: +... +width +: +50 +height +: +50 +origin_x +: +25.0 +origin_y +: +25.0 +``` + +Language: unknown +File: datum +``` +ros2 +launch +nav2_gps_waypoint_follower_demo +gps_waypoint_follower.launch.py +use_rviz: += +True + +``` + +Language: unknown +File: nav2_simple_commander +``` +ros2 +run +nav2_gps_waypoint_follower_demo +interactive_waypoint_follower + +``` + +Language: unknown +File: yaml +``` +waypoints +: +- +latitude +: +38.161491054181276 +longitude +: +-122.45464431092836 +yaw +: +0.0 +- +latitude +: +38.161587576524845 +longitude +: +-122.4547994038464 +yaw +: +1.57 +``` + +Language: unknown +File: yaml +``` +ros2 +run +nav2_gps_waypoint_follower_demo +gps_waypoint_logger + + +``` + +Language: unknown +File: nav2_gps_waypoint_follower_demo +``` +ros2 +run +nav2_gps_waypoint_follower_demo +logged_waypoint_follower + + +``` diff --git "a/exported_docs/nav2/Navigating with Keepout Zones\357\203\201.txt" "b/exported_docs/nav2/Navigating with Keepout Zones\357\203\201.txt" new file mode 100644 index 0000000..b8df354 --- /dev/null +++ "b/exported_docs/nav2/Navigating with Keepout Zones\357\203\201.txt" @@ -0,0 +1,732 @@ +Title: Navigating with Keepout Zones +URL: https://docs.nav2.org/tutorials/docs/navigation2_with_keepout_filter.html#configure-costmap-filter-info-publisher-server +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to simply utilize keep-out/safety zones where robots can’t enter and preferred lanes for robots moving in industrial environments and warehouses. All this functionality is being covered byKeepoutFiltercostmap filter plugin which will be enabled and used in this document. + +## Requirements +It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install. + +## Tutorial Steps + + +## 1. Prepare filter mask +As was written inNavigation Concepts, any Costmap Filter (including Keepout Filter) are reading the data marked in a filter mask file. Filter mask - is the usual Nav2 2D-map distributed through PGM, PNG or BMP raster file with its metadata containing in a YAML file. The following steps help to understand how to make a new filter mask: +Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from aNav2repository to a newkeepout_mask.pgmfile. +Openkeepout_mask.pgmin your favourite raster graphics editor (as an example could be taken GIMP editor). The lightness of each pixel on the mask means an encoded information for the specific costmap filter you are going to use. Color lightness of each pixel belongs to the[0..255]range (or[0..100]in percent scale), where0means black color and255- white. Another term “darkness” will be understood as the exact opposite of lightness. In other wordscolor_darkness=100%-color_lightness. +In the GIMP lightness is expressed through color components value (e.g.Rin percent scale) and might be set by movingLslider in color changing tool: +The incoming mask file is being read by the Map Server and converted intoOccupancyGridvalues from[0..100]range (where0means free cell,100- occupied, anything in between - less or more occupied cells on map) or be equal to-1for unknown value. In Nav2 stack each map hasmodeattribute which could betrinary,scaleorraw. Depending onmodeselected, the color lightness of PGM/PNG/BMP is being converted toOccupancyGridby one of the following principles: +wherefree_threshandoccupied_threshthresholds are expressed in percentage of maximum lightness/darkness level (255). Map mode and thresholds are placed in YAML metadata file (see below) asmode,free_threshandoccupied_threshfields. +For Keepout FilterOccupancyGridvalue is proportional to the passibility of area corresponding to this cell: higher values means more impassable areas. Cells with occupied values covers keep-out zones where robot will never enter or pass through.KeepoutFiltercan also act as a “weighted areas layer” by setting theOccupancyGridto something between[1-99]non-occupied values. Robot is allowed to move in these areas, however its presence there would be “undesirable” there (the higher the value, the sooner planners will try to get the robot out of this area). +Keepout Filter also covers preferred lanes case, where robots should moving only on pre-defined lanes and permitted areas e.g. in warehouses. To use this feaure you need to prepare the mask image where the lanes and permitted areas will be marked with free values while all other areas will be occupied. TIP for drawing the mask in atrinaryorscalemode: typically, amount of pixels belonging to lanes are much less than pixels covering other areas. In this case initially all lanes data might be drawn with a black pencil over white background and then (just before saving a PGM) “color inversion” tool in a image raster editor might be used. +For simplicity, in the example fill the areas with black color (intrinarymode this means occupied map) that you are going to mark as a keep-out zones: +After all keepout areas will be filled save thekeepout_mask.pgmimage. +Like all other maps, filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltokeepout_mask.yaml. Openkeepout_mask.yamland correctimagefield to a newly made PGM mask: +Since filter mask image was created as a copy of main map, other fields of YAML-file do not need to be changed. Savekeepout_mask.yamland new filter mask is ready to use. + +## 2. Configure Costmap Filter Info Publisher Server +Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in a messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter mask. +In order to enable Keepout Filter in your configuration, both servers should be enabled as a lifecycle nodes in Python launch-file. It is also possible to add them as Composition Nodes to your Navigation Component Container, which might look as follows: +where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below: +Note, that: +Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Keepout Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows: + +## 3. Enable Keepout Filter +Costmap Filters are Costamp2D plugins. You can enable theKeepoutFilterplugin in Costmap2D by addingkeepout_filterto thepluginsparameter innav2_params.yaml. You can place it in theglobal_costmapfor planning with keepouts andlocal_costmapto make sure the robot won’t attempt to drive through a keepout zone. The KeepoutFilter plugin should have the following parameters defined: +Full list of parameters supported byKeepoutFilterare listed atKeepout Filter Parameterspage. +It is important to note that enablingKeepoutFilterforglobal_costmaponly will cause the path planner to build plans bypassing keepout zones. EnablingKeepoutFilterforlocal_costmaponly will cause the robot to not enter keepout zones, but the path may still go through them. So, the best practice is to enableKeepoutFilterfor global and local costmaps simultaneously by adding it both inglobal_costmapandlocal_costmapinnav2_params.yaml. However it does not always have to be true. In some cases keepout zones don’t have to be the same for global and local costmaps, e.g. if the robot doesn’t allowed to intentionally go inside keepout zones, but if its there, the robot can drive in and out really quick if it clips an edge or corner. For this case, there is not need to use extra resources of the local costmap copy. +To enableKeepoutFilterwith same mask for both global and local costmaps, use the following configuration: + +## 4. Run Nav2 stack +After Costmap Filter Info Publisher Server and Map Server were launched and Keepout Filter was enabled for global/local costmaps, run Nav2 stack as written inGetting Started: +And check that filter is working properly as in the pictures below (first picture shows keepout filter enabled for the global costmap, second - differently-sizedkeepout_mask.pgmfilter mask): + +Code Examples: + +Language: unknown +File: image +``` +image: turtlebot3_world.pgm +-> +image: keepout_mask.pgm + +``` + +Language: unknown +File: OccupancyGrid +``` +import +os +from +ament_index_python.packages +import +get_package_share_directory +from +launch +import +LaunchDescription +from +launch.actions +import +DeclareLaunchArgument +, +GroupAction +from +launch.conditions +import +IfCondition +from +launch.substitutions +import +LaunchConfiguration +, +PythonExpression +from +launch.substitutions +import +NotEqualsSubstitution +from +launch_ros.actions +import +Node +, +LoadComposableNodes +from +launch_ros.actions +import +PushRosNamespace +from +launch_ros.descriptions +import +ComposableNode +from +nav2_common.launch +import +RewrittenYaml +def +generate_launch_description +(): +# Get the launch directory +costmap_filters_demo_dir += +get_package_share_directory +( +'nav2_costmap_filters_demo' +) +lifecycle_nodes += +[ +'filter_mask_server' +, +'costmap_filter_info_server' +] +# Parameters +namespace += +LaunchConfiguration +( +'namespace' +) +use_sim_time += +LaunchConfiguration +( +'use_sim_time' +) +autostart += +LaunchConfiguration +( +'autostart' +) +params_file += +LaunchConfiguration +( +'params_file' +) +mask_yaml_file += +LaunchConfiguration +( +'mask' +) +use_composition += +LaunchConfiguration +( +'use_composition' +) +container_name += +LaunchConfiguration +( +'container_name' +) +container_name_full += +( +namespace +, +'/' +, +container_name +) +# Declare the launch arguments +declare_namespace_cmd += +DeclareLaunchArgument +( +'namespace' +, +default_value += +'' +, +description += +'Top-level namespace' +) +declare_use_sim_time_cmd += +DeclareLaunchArgument +( +'use_sim_time' +, +default_value += +'true' +, +description += +'Use simulation (Gazebo) clock if true' +) +declare_autostart_cmd += +DeclareLaunchArgument +( +'autostart' +, +default_value += +'true' +, +description += +'Automatically startup the nav2 stack' +) +declare_params_file_cmd += +DeclareLaunchArgument +( +'params_file' +, +description += +'Full path to the ROS2 parameters file to use' +) +declare_mask_yaml_file_cmd += +DeclareLaunchArgument +( +'mask' +, +description += +'Full path to filter mask yaml file to load' +) +declare_use_composition_cmd += +DeclareLaunchArgument +( +'use_composition' +, +default_value += +'True' +, +description += +'Use composed bringup if True' +) +declare_container_name_cmd += +DeclareLaunchArgument +( +'container_name' +, +default_value += +'nav2_container' +, +description += +'The name of container that nodes will load in if use composition' +) +# Make re-written yaml +param_substitutions += +{ +'use_sim_time' +: +use_sim_time +, +'yaml_filename' +: +mask_yaml_file +} +configured_params += +RewrittenYaml +( +source_file += +params_file +, +root_key += +namespace +, +param_rewrites += +param_substitutions +, +convert_types += +True +) +load_nodes += +GroupAction +( +condition += +IfCondition +( +PythonExpression +([ +'not ' +, +use_composition +])), +actions += +[ +Node +( +package += +'nav2_map_server' +, +executable += +'map_server' +, +name += +'filter_mask_server' +, +namespace += +namespace +, +output += +'screen' +, +emulate_tty += +True +, +# https://github.com/ros2/launch/issues/188 +parameters += +[ +configured_params +]), +Node +( +package += +'nav2_map_server' +, +executable += +'costmap_filter_info_server' +, +name += +'costmap_filter_info_server' +, +namespace += +namespace +, +output += +'screen' +, +emulate_tty += +True +, +# https://github.com/ros2/launch/issues/188 +parameters += +[ +configured_params +]), +Node +( +package += +'nav2_lifecycle_manager' +, +executable += +'lifecycle_manager' +, +name += +'lifecycle_manager_costmap_filters' +, +namespace += +namespace +, +output += +'screen' +, +emulate_tty += +True +, +# https://github.com/ros2/launch/issues/188 +parameters += +[{ +'use_sim_time' +: +use_sim_time +}, +{ +'autostart' +: +autostart +}, +{ +'node_names' +: +lifecycle_nodes +}]) +] +) +load_composable_nodes += +GroupAction +( +condition += +IfCondition +( +use_composition +), +actions += +[ +PushRosNamespace +( +condition += +IfCondition +( +NotEqualsSubstitution +( +LaunchConfiguration +( +'namespace' +), +'' +)), +namespace += +namespace +), +LoadComposableNodes +( +target_container += +container_name_full +, +composable_node_descriptions += +[ +ComposableNode +( +package += +'nav2_map_server' +, +plugin += +'nav2_map_server::MapServer' +, +name += +'filter_mask_server' +, +parameters += +[ +configured_params +]), +ComposableNode +( +package += +'nav2_map_server' +, +plugin += +'nav2_map_server::CostmapFilterInfoServer' +, +name += +'costmap_filter_info_server' +, +parameters += +[ +configured_params +]), +ComposableNode +( +package += +'nav2_lifecycle_manager' +, +plugin += +'nav2_lifecycle_manager::LifecycleManager' +, +name += +'lifecycle_manager_costmap_filters' +, +parameters += +[{ +'use_sim_time' +: +use_sim_time +}, +{ +'autostart' +: +autostart +}, +{ +'node_names' +: +lifecycle_nodes +}]), +] +) +] +) +ld += +LaunchDescription +() +ld +. +add_action +( +declare_namespace_cmd +) +ld +. +add_action +( +declare_use_sim_time_cmd +) +ld +. +add_action +( +declare_autostart_cmd +) +ld +. +add_action +( +declare_params_file_cmd +) +ld +. +add_action +( +declare_mask_yaml_file_cmd +) +ld +. +add_action +( +declare_use_composition_cmd +) +ld +. +add_action +( +declare_container_name_cmd +) +ld +. +add_action +( +load_nodes +) +ld +. +add_action +( +load_composable_nodes +) +return +ld +``` + +Language: unknown +File: params_file +``` +costmap_filter_info_server +: +ros__parameters +: +use_sim_time +: +true +type +: +0 +filter_info_topic +: +"/costmap_filter_info" +mask_topic +: +"/keepout_filter_mask" +base +: +0.0 +multiplier +: +1.0 +filter_mask_server +: +ros__parameters +: +use_sim_time +: +true +frame_id +: +"map" +topic_name +: +"/keepout_filter_mask" +yaml_filename +: +"keepout_mask.yaml" +``` + +Language: unknown +File: costmap_filter_info.launch.py +``` +$ +mkdir +-p +~/tutorials_ws/src +$ +cd +~/tutorials_ws/src +$ +git +clone +https://github.com/ros-navigation/navigation2_tutorials.git +$ +cd +~/tutorials_ws +$ +colcon +build +--symlink-install +--packages-select +nav2_costmap_filters_demo +$ +source +~/tutorials_ws/install/setup.bash +$ +ros2 +launch +nav2_costmap_filters_demo +costmap_filter_info.launch.py +params_file: += +` +pwd +` +/src/navigation2_tutorials/nav2_costmap_filters_demo/params/keepout_params.yaml +mask: += +` +pwd +` +/src/navigation2_tutorials/nav2_costmap_filters_demo/maps/keepout_mask.yaml +use_composition: += +True + +``` + +Language: unknown +File: KeepoutFilter +``` +global_costmap: + global_costmap: + ros__parameters: + ... + plugins: ["static_layer", "obstacle_layer", "inflation_layer"] + filters: ["keepout_filter"] + ... + keepout_filter: + plugin: "nav2_costmap_2d::KeepoutFilter" + enabled: True + filter_info_topic: "/costmap_filter_info" +... +local_costmap: + local_costmap: + ros__parameters: + ... + plugins: ["voxel_layer", "inflation_layer"] + filters: ["keepout_filter"] + ... + keepout_filter: + plugin: "nav2_costmap_2d::KeepoutFilter" + enabled: True + filter_info_topic: "/costmap_filter_info" + +``` + +Language: unknown +File: filters +``` +ros2 +launch +nav2_bringup +tb3_simulation_launch.py + +``` diff --git "a/exported_docs/nav2/Navigating with Speed Limits\357\203\201.txt" "b/exported_docs/nav2/Navigating with Speed Limits\357\203\201.txt" new file mode 100644 index 0000000..e8b5788 --- /dev/null +++ "b/exported_docs/nav2/Navigating with Speed Limits\357\203\201.txt" @@ -0,0 +1,588 @@ +Title: Navigating with Speed Limits +URL: https://docs.nav2.org/tutorials/docs/navigation2_with_speed_filter.html#enable-speed-filter +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to simply utilize Speed Filter which is designed to limit the maximum speed of robots in speed restriction areas marked on a map. This functionality is being covered bySpeedFiltercostmap filter plugin which will be enabled and used in this document. + +## Requirements +It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that the Nav2 project is also built locally as it was made inBuild and Install. + +## Tutorial Steps + + +## 1. Prepare filter mask +As was written inNavigation Concepts, any Costmap Filter (including Speed Filter) is reading the data marked in a filter mask file. All information about filter masks, their types, detailed structure and how to make a new one is written in aNavigating with Keepout Zonestutorial at1.Preparefiltermaskschapter. The principal of drawing the filter mask for Speed Filter is the same as for Keepout Filter (to annotate a map with the requested zones), except thatOccupancyGridmask values have another meaning: these values are encoded speed limits for the areas corresponding to the cell on map. +Let’s look, how it is being decoded. As we know,OccupancyGridvalues are belonging to the[0..100]range. For Speed Filter0value means no speed limit in the area corresponding zero-cell on mask. Values from[1..100]range are being linearly converted into a speed limit value by the following formula: +where: +The decodedspeed_limitvalue may have one of two meanings: +The meaning used by Speed Filter is being read fromnav2_msgs/CostmapFilterInfomessages. +In this tutorial we will use the first type of speed restriction expressed in a percent from maximum robot speed. +Create a new image with a PGM/PNG/BMP format: copyturtlebot3_world.pgmmain map which will be used in a world simulation from a Nav2 repository to a newspeed_mask.pgmfile. Openspeed_mask.pgmin your favourite raster graphics editor and fill speed restricted areas with grey colors. In our example darker colors will indicate areas with higher speed restriction: +Area “A” is filled with40%gray color, area “B” - with70%gray, that means that speed restriction will take100%-40%=60%in area “A” and100%-70%=30%in area “B” from maximum speed value allowed for this robot. +We will usescalemap mode with no thresholds. In this mode darker colors will have higherOccupancyGridvalues. E.g. for area “B” with70%of grayOccupancyGriddata will be equal to70. So in order to hit the target, we need to choosebase=100.0andmultiplier=-1.0. This will reverse the scaleOccupancyGridvalues to a desired one. No thresholds (free_threshoccupied_thresh) were chosen for the convenience in theyamlfile: to have 1:1 full range conversion of lightness value from filter mask -> to speed restriction percent. +After all speed restriction areas will be filled, save thespeed_mask.pgmimage. +Like all other maps, the filter mask should have its own YAML metadata file. Copyturtlebot3_world.yamltospeed_mask.yaml. Openspeed_mask.yamland update the fields as shown below (as mentioned before for thescalemode to use whole color lightness range there should be no thresholds:free_thresh=0.0andoccupied_thresh=1.0): +Since Costmap2D does not support orientation, the last third “yaw” component of theoriginvector should be equal to zero (for example:origin:[1.25,-5.18,0.0]). Savespeed_mask.yamland the new filter mask is ready to use. + +## 2. Configure Costmap Filter Info Publisher Server +Each costmap filter reads incoming meta-information (such as filter type or data conversion coefficients) in messages ofnav2_msgs/CostmapFilterInfotype. These messages are being published byCostmap Filter Info Publisher Server. The server is running as a lifecycle node. According to thedesign document,nav2_msgs/CostmapFilterInfomessages are going in a pair withOccupancyGridfilter mask topic. Therefore, along with Costmap Filter Info Publisher Server there should be enabled a new instance of Map Server configured to publish filter masks. +In order to enable Speed Filter in your configuration, both servers should be enabled as lifecycle nodes in Python launch-file. For example, this might look as follows, though adding them as Composition Nodes to your Navigation Component Container is also possible: +where theparams_filevariable should be set to a YAML-file having ROS parameters for Costmap Filter Info Publisher Server and Map Server nodes. These parameters and their meaning are listed atMap Server / Saverpage. Please, refer to it for more information. The example ofparams_filecould be found below: +Note, that: +Ready-to-go standalone Python launch-script, YAML-file with ROS parameters and filter mask example for Speed Filter could be found in anav2_costmap_filters_demodirectory ofnavigation2_tutorialsrepository. To simply run Filter Info Publisher Server and Map Server tuned on Turtlebot3 standard simulation written atGetting Started, build the demo and launchcostmap_filter_info.launch.pyas follows: + +## 3. Enable Speed Filter +Costmap Filters are Costmap2D plugins. You can enable theSpeedFilterplugin in Costmap2D by addingspeed_filterto thepluginsparameter innav2_params.yaml. The Speed Filter plugin should have the following parameters defined: +Full list of parameters supported bySpeedFilterare listed at theSpeed Filter Parameterspage. +You can place the plugin either in theglobal_costmapsection innav2_params.yamlto have speed restriction mask applied to global costmap or in thelocal_costmapto apply speed mask to the local costmap. However,SpeedFilterplugin should never be enabled simultaneously for global and local costmaps. Otherwise, it can lead to unwanted multiple “speed restriction” - “no restriction” message chains on speed restriction boundaries, that will cause jerking of the robot or another unpredictable behaviour. +In this tutorial, we will enable Speed Filter for the global costmap. For this use the following configuration: +As stated in thedesign, Speed Filter publishes speed restrictingmessagestargeted for a Controller Server so that it could restrict maximum speed of the robot when it needed. Controller Server has aspeed_limit_topicROS parameter for that, which should be set to the same as inspeed_filterplugin value. This topic in the map server could also be used to any number of other speed-restricted applications beyond the speed limiting zones, such as dynamically adjusting maximum speed by payload mass. +Setspeed_limit_topicparameter of a Controller Server to the same value as it set forspeed_filterplugin: + +## 4. Run Nav2 stack +After Costmap Filter Info Publisher Server and Map Server were launched and Speed Filter was enabled for global/local costmap, run Nav2 stack as written inGetting Started: +For better visualization of speed filter mask, in RViz in the leftDisplayspane unfoldMapand changeTopicfrom/map-> to/speed_filter_mask. +Set the goal behind the speed restriction areas and check that the filter is working properly: robot should slow down when going through a speed restricting areas. Below is how it might look (first picture shows speed filter enabled for the global costmap, second -speed_mask.pgmfilter mask): + +Code Examples: + +Language: unknown +File: [1..100] +``` +speed_limit += +filter_mask_data +* +multiplier ++ +base +; +``` + +Language: unknown +File: occupied_thresh=1.0 +``` +image +: +turtlebot3_world.pgm +-> +image +: +speed_mask.pgm +mode +: +trinary +-> +mode +: +scale +occupied_thresh +: +0.65 +free_thresh +: +0.196 +-> +occupied_thresh +: +1.0 +free_thresh +: +0.0 +``` + +Language: unknown +File: OccupancyGrid +``` +import +os +from +ament_index_python.packages +import +get_package_share_directory +from +launch +import +LaunchDescription +from +launch.actions +import +DeclareLaunchArgument +from +launch.substitutions +import +LaunchConfiguration +from +launch_ros.actions +import +Node +from +nav2_common.launch +import +RewrittenYaml +def +generate_launch_description +(): +# Get the launch directory +costmap_filters_demo_dir += +get_package_share_directory +( +'nav2_costmap_filters_demo' +) +# Create our own temporary YAML files that include substitutions +lifecycle_nodes += +[ +'filter_mask_server' +, +'costmap_filter_info_server' +] +# Parameters +namespace += +LaunchConfiguration +( +'namespace' +) +use_sim_time += +LaunchConfiguration +( +'use_sim_time' +) +autostart += +LaunchConfiguration +( +'autostart' +) +params_file += +LaunchConfiguration +( +'params_file' +) +mask_yaml_file += +LaunchConfiguration +( +'mask' +) +# Declare the launch arguments +declare_namespace_cmd += +DeclareLaunchArgument +( +'namespace' +, +default_value += +'' +, +description += +'Top-level namespace' +) +declare_use_sim_time_cmd += +DeclareLaunchArgument +( +'use_sim_time' +, +default_value += +'true' +, +description += +'Use simulation (Gazebo) clock if true' +) +declare_autostart_cmd += +DeclareLaunchArgument +( +'autostart' +, +default_value += +'true' +, +description += +'Automatically startup the nav2 stack' +) +declare_params_file_cmd += +DeclareLaunchArgument +( +'params_file' +, +default_value += +os +. +path +. +join +( +costmap_filters_demo_dir +, +'params' +, +'speed_params.yaml' +), +description += +'Full path to the ROS 2 parameters file to use' +) +declare_mask_yaml_file_cmd += +DeclareLaunchArgument +( +'mask' +, +default_value += +os +. +path +. +join +( +costmap_filters_demo_dir +, +'maps' +, +'speed_mask.yaml' +), +description += +'Full path to filter mask yaml file to load' +) +# Make re-written yaml +param_substitutions += +{ +'use_sim_time' +: +use_sim_time +, +'yaml_filename' +: +mask_yaml_file +} +configured_params += +RewrittenYaml +( +source_file += +params_file +, +root_key += +namespace +, +param_rewrites += +param_substitutions +, +convert_types += +True +) +# Nodes launching commands +start_lifecycle_manager_cmd += +Node +( +package += +'nav2_lifecycle_manager' +, +executable += +'lifecycle_manager' +, +name += +'lifecycle_manager_costmap_filters' +, +namespace += +namespace +, +output += +'screen' +, +emulate_tty += +True +, +# https://github.com/ros2/launch/issues/188 +parameters += +[{ +'use_sim_time' +: +use_sim_time +}, +{ +'autostart' +: +autostart +}, +{ +'node_names' +: +lifecycle_nodes +}]) +start_map_server_cmd += +Node +( +package += +'nav2_map_server' +, +executable += +'map_server' +, +name += +'filter_mask_server' +, +namespace += +namespace +, +output += +'screen' +, +emulate_tty += +True +, +# https://github.com/ros2/launch/issues/188 +parameters += +[ +configured_params +]) +start_costmap_filter_info_server_cmd += +Node +( +package += +'nav2_map_server' +, +executable += +'costmap_filter_info_server' +, +name += +'costmap_filter_info_server' +, +namespace += +namespace +, +output += +'screen' +, +emulate_tty += +True +, +# https://github.com/ros2/launch/issues/188 +parameters += +[ +configured_params +]) +ld += +LaunchDescription +() +ld +. +add_action +( +declare_namespace_cmd +) +ld +. +add_action +( +declare_use_sim_time_cmd +) +ld +. +add_action +( +declare_autostart_cmd +) +ld +. +add_action +( +declare_params_file_cmd +) +ld +. +add_action +( +declare_mask_yaml_file_cmd +) +ld +. +add_action +( +start_lifecycle_manager_cmd +) +ld +. +add_action +( +start_map_server_cmd +) +ld +. +add_action +( +start_costmap_filter_info_server_cmd +) +return +ld +``` + +Language: unknown +File: params_file +``` +costmap_filter_info_server +: +ros__parameters +: +use_sim_time +: +true +type +: +1 +filter_info_topic +: +"/costmap_filter_info" +mask_topic +: +"/speed_filter_mask" +base +: +100.0 +multiplier +: +-1.0 +filter_mask_server +: +ros__parameters +: +use_sim_time +: +true +frame_id +: +"map" +topic_name +: +"/speed_filter_mask" +yaml_filename +: +"speed_mask.yaml" +``` + +Language: unknown +File: costmap_filter_info.launch.py +``` +$ +mkdir +-p +~/tutorials_ws/src +$ +cd +~/tutorials_ws/src +$ +git +clone +https://github.com/ros-navigation/navigation2_tutorials.git +$ +cd +~/tutorials_ws +$ +colcon +build +--symlink-install +--packages-select +nav2_costmap_filters_demo +$ +source +~/tutorials_ws/install/setup.bash +$ +ros2 +launch +nav2_costmap_filters_demo +costmap_filter_info.launch.py +params_file: += +src/navigation2_tutorials/nav2_costmap_filters_demo/params/speed_params.yaml +mask: += +src/navigation2_tutorials/nav2_costmap_filters_demo/maps/speed_mask.yaml + +``` + +Language: unknown +File: SpeedFilter +``` +global_costmap: + global_costmap: + ros__parameters: + ... + plugins: ["static_layer", "obstacle_layer", "inflation_layer"] + filters: ["speed_filter"] + ... + speed_filter: + plugin: "nav2_costmap_2d::SpeedFilter" + enabled: True + filter_info_topic: "/costmap_filter_info" + speed_limit_topic: "/speed_limit" + +``` + +Language: unknown +File: speed_filter +``` +controller_server: + ros__parameters: + ... + speed_limit_topic: "/speed_limit" + +``` + +Language: unknown +File: speed_filter +``` +ros2 +launch +nav2_bringup +tb3_simulation_launch.py + +``` diff --git "a/exported_docs/nav2/Navigating with a Physical Turtlebot 3\357\203\201.txt" "b/exported_docs/nav2/Navigating with a Physical Turtlebot 3\357\203\201.txt" new file mode 100644 index 0000000..0951d75 --- /dev/null +++ "b/exported_docs/nav2/Navigating with a Physical Turtlebot 3\357\203\201.txt" @@ -0,0 +1,73 @@ +Title: Navigating with a Physical Turtlebot 3 +URL: https://docs.nav2.org/tutorials/docs/navigation2_on_real_turtlebot3.html#requirements +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to control and navigate Turtlebot 3 using the ROS 2 Nav2 on a physical Turtlebot 3 robot. +Before completing this tutorials, completingGetting Startedis highly recommended especially if you are new to ROS and Nav2. +This tutorial may take about 1 hour to complete. +It depends on your experience with ROS, robots, and what computer system you have. + +## Requirements +You must install Nav2, Turtlebot3. +If you don’t have them installed, please followGetting Started. +The turtlebot3 software can be installed via the following or on theturtlebot3 repository: + +## Tutorial Steps + + +## 0- Setup Your Environment Variables +Run the following commands first whenever you open a new terminal during this tutorial. + +## 1- Launch Turtlebot 3 +You will need to launch your robot’s interface, for example: + +## 2- Launch Nav2 +You need to have a map of the environment where you want to Navigate Turtlebot 3, or create one live with SLAM. +In case you are interested, there is a use case tutorial which shows how to use Nav2 with SLAM.(SLAM) Navigating While Mapping. +Required files: +.yamlis the configuration file for the map we want to provide Nav2. +In this case, it has the map resolution value, threshold values for obstacles and free spaces, and a map file location. +You need to make sure these values are correct. +More information about the map.yaml can be foundhere. +Launch Nav2. If you set autostart:=False, you need to click on the start button in RViz to initialize the nodes. +Make sureuse_sim timeis set toFalse, because we want to use the system time instead of the time simulation time from Gazebo. +ros2launchnav2_bringupbringup_launch.pyuse_sim_time:=Falseautostart:=Falsemap:=/path/to/your-map.yaml +Note: Don’t forget to change/path/to/your-map.yamlto the actual path to the your-map.yaml file. + +## 3- Launch RVIZ +Launch RVIZ with a pre-defined configuration file. +Now, you should see a shadow of Turtlebot 3 robot model in the center of the plot in Rviz. +Click on the Start button (Bottom Left) if you set the auto_start parameter to false. +Then, the map should appear in RViz. + +## 4- Initialize the Location of Turtlebot 3 +First, find where the robot is on the map. Check where your robot is in the room. +Set the pose of the robot in RViz. +Click on the 2D Pose Estimate button and point the location of the robot on the map. +The direction of the green arrow is the orientation of Turtlebot. +Now, the 3D model of Turtlebot should move to that location. +A small error in the estimated location is tolerable. + +## 5- Send a Goal Pose +Pick a target location for Turtlebot on the map. +You can send Turtlebot 3 a goal position and a goal orientation by using theNav2 Goalor theGoalToolbuttons. +Note: Nav2 Goal button uses a ROS 2 Action to send the goal and the GoalTool publishes the goal to a topic. +Once you define the target pose, Nav2 will find a global path and start navigating the robot on the map. +Now, you can see that Turtlebot 3 moves towards the goal position in the room. See the video below. + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +sudo +apt +install +ros--turtlebot3 +ros--turtlebot3-msgs +ros--turtlebot3-bringup + +``` diff --git "a/exported_docs/nav2/Navigation Concepts\357\203\201.txt" "b/exported_docs/nav2/Navigation Concepts\357\203\201.txt" new file mode 100644 index 0000000..389a190 --- /dev/null +++ "b/exported_docs/nav2/Navigation Concepts\357\203\201.txt" @@ -0,0 +1,221 @@ +Title: Navigation Concepts +URL: https://docs.nav2.org/concepts/index.html +Section: concepts/index.html +-------------------------------------------------------------------------------- + + +## ROS 2 +ROS 2 is the core middleware used for Nav2. If you are unfamiliar with this, please visitthe ROS 2 documentationbefore continuing. + +## Action Server +Just as in ROS, action servers are a common way to control long running tasks like navigation. +This stack makes more extensive use of actions, and in some cases, without an easy topic interface. +It is more important to understand action servers as a developer in ROS 2. +Some simple CLI examples can be found in theROS 2 documentation. +Action servers are similar to a canonical service server. +A client will request some task to be completed, except, this task may take a long time. +An example would be moving the shovel up from a bulldozer or ask a robot to travel 10 meters to the right. +In this situation, action servers and clients allow us to call a long-running task in another process or thread and return a future to its result. +It is permissible at this point to block until the action is complete, however, you may want to occasionally check if the action is complete and continue to process work in the client thread. +Since it is long-running, action servers will also provide feedback to their clients. +This feedback can be anything and is defined in the ROS.actionalong with the request and result types. +In the bulldozer example, a request may be an angle, a feedback may be the angle remaining to be moved, and the result is a success or fail boolean with the end angle. +In the navigation example, a request may be a position, a feedback may be the time its been navigating for and the distance to the goal, and the result a boolean for success. +Feedback and results can be gathered synchronously by registering callbacks with the action client. +They may also be gathered by asynchronously requesting information from the shared future objects. +Both require spinning the client node to process callback groups. +Action servers are used in this stack to communicate with the highest level Behavior Tree (BT) navigator through aNavigateToPoseaction message. +They are also used for the BT navigator to communicate with the subsequent smaller action servers to compute plans, control efforts, and recoveries. +Each will have their own unique.actiontype innav2_msgsfor interacting with the servers. + +## Lifecycle Nodes and Bond +Lifecycle (or Managed, more correctly) nodes are unique to ROS 2. +More information can befound here. +They are nodes that contain state machine transitions for bringup and teardown of ROS 2 servers. +This helps in deterministic behavior of ROS systems in startup and shutdown. +It also helps users structure their programs in reasonable ways for commercial uses and debugging. +When a node is started, it is in the unconfigured state, only processing the node’s constructor which shouldnotcontain any ROS networking setup or parameter reading. +By the launch system, or the supplied lifecycle manager, the nodes need to be transitioned to inactive by configuring. +After, it is possible to activate the node by transitioning through the activating stage. +This state will allow the node to process information and be fully setup to run. +The configuration stage, triggering theon_configure()method, will setup all parameters, ROS networking interfaces, and for safety systems, all dynamically allocated memory. +The activation stage, triggering theon_activate()method, will active the ROS networking interfaces and set any states in the program to start processing information. +To shutdown, we transition into deactivating, cleaning up, shutting down and end in the finalized state. +The networking interfaces are deactivated and stop processing, deallocate memory, exit cleanly, in those stages, respectively. +The lifecycle node framework is used extensively through out this project and all servers utilize it. +It is best convention for all ROS systems to use lifecycle nodes if it is possible. +Within Nav2, we use a wrapper of LifecycleNodes,nav2_utilLifecycleNode. +This wrapper wraps much of the complexities of LifecycleNodes for typical applications. +It also includes abondconnection for the lifecycle manager to ensure that after a server transitions up, it also remains active. +If a server crashes, it lets the lifecycle manager know and transition down the system to prevent a critical failure. SeeEloquent to Foxyfor details. + +## Behavior Trees +Behavior trees (BT) are becoming increasingly common in complex robotics tasks. +They are a tree structure of tasks to be completed. +It creates a more scalable and human-understandable framework for defining multi-step or many state applications. +This is opposed to a finite state machine (FSM) which may have dozens of states and hundreds of transitions. +An example would be a soccer-playing robot. +Embedding the logic of soccer game play into a FSM would be challenging and error prone with many possible states and rules. +Additionally, modeling choices like to shoot at the goal from the left, right, or center, is particularly unclear. +With a BT, basic primitives, like “kick”, “walk”, “go to ball”, can be created and reused for many behaviors. +More information can be foundin this book. +Istronglyrecommend reading chapters 1-3 to get a good understanding of the nomenclature and workflow. +It should only take about 30 minutes. +Behavior Trees provide a formal structure for navigation logic which can be both used to create complex systems but also be verifiable and validated as provenly correct using advanced tools. Having the application logic centralized in the behavior tree and with independent task servers (which only communicate data over the tree) allows for formal analysis. +For this project, we useBehaviorTree CPP V4as the behavior tree library. +We create node plugins which can be constructed into a tree, inside theBTNavigator. +The node plugins are loaded into the BT and when the XML file of the tree is parsed, the registered names are associated. +At this point, we can march through the behavior tree to navigate. +One reason this library is used is its ability to load subtrees. This means that the Nav2 behavior tree can be loaded into another higher-level BT to use this project as node plugin. +An example would be in soccer play, using the Nav2 behavior tree as the “go to ball” node with a ball detection as part of a larger task. +Additionally, we supply aNavigateToPoseActionplugin (among others) for BT so the Nav2 stack can be called from a client application through the usual action interface. +Other systems could be used to design complex autonomous behavior, namely Hierarchical FSMs (HFSM). +Behavior Trees were selected due to popularity across the robotics and related industries and by largely user demand. +However, due to the independent task server nature of Nav2, it is not difficult to offer anav2_hfsm_navigatorpackage in the future, pending interest and contribution. + +## Navigation Servers +Planners and controllers are at the heart of a navigation task. +Recoveries are used to get the robot out of a bad situation or attempt to deal with various forms of issues to make the system fault-tolerant. +Smoothers can be used for additional quality improvements of the planned path. +In this section, the general concepts around them and their uses in this project are analyzed. + +## Planner, Controller, Smoother and Recovery Servers +Four of the action servers in this project are the planner, behavior, smoother and controller servers. +These action servers are used to host a map of algorithm plugins to complete various tasks. +They also host the environmental representation used by the algorithm plugins to compute their outputs. +The planner, smoother and controller servers will be configured at runtime with the names (aliases) and types of algorithms to use. +These types are the pluginlib names that have been registered and the names are the aliases for the task. +An example would be the DWB controller used with nameFollowPath, as it follows a reference path. +In this case, then all parameters for DWB would be placed in that namespace, e.g.FollowPath.. +These three servers then expose an action interface corresponding to their task. +When the behavior tree ticks the corresponding BT node, it will call the action server to process its task. +The action server callback inside the server will call the chosen algorithm by its name (e.g.FollowPath) that maps to a specific algorithm. +This allows a user to abstract the algorithm used in the behavior tree to classes of algorithms. +For instance, you can haveNplugin controllers to follow paths, dock with charger, avoid dynamic obstacles, or interface with a tool. +Having all of these plugins in the same server allows the user to make use of a single environmental representation object, which is costly to duplicate. +For the behavior server, each of the behaviors also contains their own name, however, each plugin will also expose its own special action server. +This is done because of the wide variety of behavior actions that may be created which cannot have a single simple interface to share. +The behavior server also contains a costmap subscriber to the local costmap, receiving real-time updates from the controller server, to compute its tasks. +We do this to avoid having multiple instances of the local costmap which are computationally expensive to duplicate. +Alternatively, since the BT nodes are trivial plugins calling an action, new BT nodes can be created to call other action servers with other action types. +It is advisable to use the provided servers if possible at all times. +If, due to the plugin or action interfaces, a new server is needed, that can be sustained with the framework. +The new server should use the new type and plugin interface, similar to the provided servers. +A new BT node plugin will need to be created to call the new action server – however no forking or modification is required in the Nav2 repo itself by making extensive use of servers and plugins. +If you find that you require a new interface to the pluginlib definition or action type, please file a ticket and see if we can rectify that in the same interfaces. + +## Planners +The task of a planner is to compute a path to complete some objective function. +The path can also be known as a route, depending on the nomenclature and algorithm selected. +Two canonical examples are computing a plan to a goal (e.g. from current position to a goal) or complete coverage (e.g. plan to cover all free space). +The planner will have access to a global environmental representation and sensor data buffered into it. +Planners can be written to: +The general task in Nav2 for the planner is to compute a valid, and potentially optimal, path from the current pose to a goal pose. +However, many classes of plans and routes exist which are supported. + +## Controllers +Controllers, also known as local planners in ROS 1, are the way we follow the globally computed path or complete a local task. +The controller will have access to a local environment representation to attempt to compute feasible control efforts for the base to follow. +Many controller will project the robot forward in space and compute a locally feasible path at each update iteration. +Controllers can be written to: +The general task in Nav2 for a controller is to compute a valid control effort to follow the global plan. +However, many classes of controllers and local planners exist. +It is the goal of this project that all controller algorithms can be plugins in this server for common research and industrial tasks. + +## Behaviors +Recovery behaviors are a mainstay of fault-tolerant systems. +The goal of recoveries are to deal with unknown or failure conditions of the system and autonomously handle them. +Examples may include faults in the perception system resulting in the environmental representation being full of fake obstacles. +The clear costmap recovery would then be triggered to allow the robot to move. +Another example would be if the robot was stuck due to dynamic obstacles or poor control. +Backing up or spinning in place, if permissible, allow the robot to move from a poor location into free space it may navigate successfully. +Finally, in the case of a total failure, a recovery may be implemented to call an operator’s attention for help. +This can be done via email, SMS, Slack, Matrix, etc. +It is important to note that the behavior server can hold any behavior to share access to expensive resources like costmaps or TF buffers, not just recovery behaviors. Each may have its own API. + +## Smoothers +As criteria for optimality of the path searched by a planner are usually reduced compared to reality, additional path refinement is often beneficial. +Smoothers have been introduced for this purpose, typically responsible for reducing path raggedness and smoothing abrupt rotations, +but also for increasing distance from obstacles and high-cost areas as the smoothers have access to a global environmental representation. +Use of a separate smoother over one that is included as part of a planner is advantageous when combining different planners with different smoothers or when a specific control over smoothing is required, e.g. smoothing only a specific part of the path. +The general task in Nav2 for a smoother is to receive a path and return its improved version. +However, for different input paths, criteria of the improvements and methods of acquiring them exist, creating space for a multitude of smoothers that can be registered in this server. + +## Robot Footprints +It is worth remarking that in the cost maps, we set a robot’s footprint either as a circle of radiusrobot_radiusor as a vector of pointsfootprintrepresenting an arbitrary polygon if the robot is non-circular. This can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers. + +## Waypoint Following +Waypoint following is a basic feature of a navigation system. It tells our system how to use navigation to get to multiple destinations. +Thenav2_waypoint_followercontains a waypoint following program with a plugin interface for specific task executors. +This is useful if you need to go to a given location and complete a specific task like take a picture, pick up a box, or wait for user input. +It is a nice demo application for how to use Nav2 in a sample application. +However, it could be used for more than just a sample application. +There are 2 schools of thoughts for fleet managers / dispatchers: +In the first, thenav2_waypoint_followeris fully sufficient to create a production-grade on-robot solution. Since the autonomy system / dispatcher is taking into account things like the robot’s pose, battery level, current task, and more when assigning tasks, the application on the robot just needs to worry about the task at hand and not the other complexities of the system to complete the requested task. In this situation, you should think of a request to the waypoint follower as 1 unit of work (e.g. 1 pick in a warehouse, 1 security patrole loop, 1 aisle, etc) to do a task and then return to the dispatcher for the next task or request to recharge. In this school of thought, the waypoint following application is just one step above navigation and below the system autonomy application. +In the second, thenav2_waypoint_followeris a nice sample application / proof of concept, but you really need your waypoint following / autonomy system on the robot to carry more weight in making a robust solution. In this case, you should use thenav2_behavior_treepackage to create a custom application-level behavior tree using navigation to complete the task. This can include subtrees like checking for the charge status mid-task for returning to dock or handling more than 1 unit of work in a more complex task. Soon, there will be anav2_bt_waypoint_follower(name subject to adjustment) that will allow you to create this application more easily. In this school of thought, the waypoint following application is more closely tied to the system autonomy, or in many cases, is the system autonomy. +Neither is better than the other, it highly depends on the tasks your robot(s) are completing, in what type of environment, and with what cloud resources available. Often this distinction is very clear for a given business case. +nav2_waypoint_followeralso supports GPS waypoint following when global localization is provided byrobot_localizationusing thenavsat_transformnode - but also may be provided by Fuse or any number of other sources. +There is an action server named/follow_gps_waypointswithinnav2_waypoint_followerthat can directly take in goals expressed in GPS coordinates, convert them to cartesian goals in the global frame, and execute them as cartesian waypoints. + +## State Estimation +Within the navigation project, there are 2 major transformations that need to be provided, according to community standards. +Themaptoodomtransform is provided by a positioning system (localization, mapping, SLAM) andodomtobase_linkby an odometry system. + +## Standards +REP 105defines the frames and conventions required for navigation and the larger ROS ecosystem. +These conventions should be followed at all times to make use of the rich positioning, odometry, and SLAM projects available in the community. +In a nutshell, REP-105 says that you must, at minimum, build a TF tree that contains a fullmap->odom->base_link->[sensorframes]for your robot. +TF2 is the time-variant transformation library in ROS 2 we use to represent and obtain time synchronized transformations. +It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation. +It is then the role of the odometry system to provide theodom->base_linktransformation. +The remainder of the transformations relative tobase_linkshould be static and defined in yourURDF. + +## Global Positioning: Localization and SLAM +It is the job of the global positioning system (GPS, SLAM, Motion Capture) to, at minimum, provide themap->odomtransformation. +We provideamclwhich is an Adaptive Monte-Carlo Localization technique based on a particle filter for localization in a static map. +We also provide SLAM Toolbox as the default SLAM algorithm for use to position and generate a static map. +These methods may also produce other output including position topics, maps, or other metadata, but they must provide that transformation to be valid. +Multiple positioning methods can be fused together using robot localization, discussed more below. + +## Odometry +It is the role of the odometry system to provide theodom->base_linktransformation. +Odometry can come from many sources including LIDAR, RADAR, wheel encoders, VIO, and IMUs. +The goal of the odometry is to provide a smooth and continuous local frame based on robot motion. +The global positioning system will update the transformation relative to the global frame to account for the odometric drift. +Robot Localizationis typically used for this fusion. +It will take inNsensors of various types and provide a continuous and smooth odometry to TF and to a topic. +A typical mobile robotics setup may have odometry from wheel encoders, IMUs, and vision fused in this manner. +The smooth output can be used then for dead-reckoning for precise motion and updating the position of the robot accurately between global position updates. + +## Environmental Representation +The environmental representation is the way the robot perceives its environment. +It also acts as the central localization for various algorithms and data sources to combine their information into a single space. +This space is then used by the controllers, planners, and recoveries to compute their tasks safely and efficiently. + +## Costmaps and Layers +The current environmental representation is a costmap. +A costmap is a regular 2D grid of cells containing a cost from unknown, free, occupied, or inflated cost. +This costmap is then searched to compute a global plan or sampled to compute local control efforts. +Various costmap layers are implemented as pluginlib plugins to buffer information into the costmap. +This includes information from LIDAR, RADAR, sonar, depth images, etc. +It may be wise to process sensor data before inputting it into the costmap layer, but that is up to the developer. +Costmap layers can be created to detect and track obstacles in the scene for collision avoidance using camera or depth sensors. +Additionally, layers can be created to algorithmically change the underlying costmap based on some rule or heuristic. +Finally, they may be used to buffer live data into the 2D or 3D world for binary obstacle marking. + +## Costmap Filters +Imagine, you’re annotating a map file (or any image file) in order to have a specific action occur based on the location in the annotated map. Examples of marking/annotating might be keep out zones to avoid planning inside, or have pixels belong to maximum speeds in marked areas. This annotated map is called “filter mask”. Just like a mask overlaid on a surface, it can or cannot be same size, pose and scale as a main map. The main goal of filter mask - is to provide the ability of marking areas on maps with some additional features or behavioral changes. +Costmap filters are a costmap layer-based approach of applying spatial-dependent behavioral changes, annotated in filter masks, into the Nav2 stack. +Costmap filters are implemented as costmap plugins. +These plugins are called “filters” as they are filtering a costmap by spatial annotations marked on filter masks. +In order to make a filtered costmap and change a robot’s behavior in annotated areas, the filter plugin reads the data coming from the filter mask. +This data is being linearly transformed into a feature map in a filter space. +Having this transformed feature map along with a map/costmap, any sensor data and current robot coordinate filters can update the underlying costmap and change the behavior of the robot depending on where it is. +For example, the following functionality could be made by use of costmap filters: + +## Other Forms +Various other forms of environmental representations exist. +These include: + +## Nav2 Academic Overview + diff --git "a/exported_docs/nav2/Navigation Plugins\357\203\201.txt" "b/exported_docs/nav2/Navigation Plugins\357\203\201.txt" new file mode 100644 index 0000000..43a5baa --- /dev/null +++ "b/exported_docs/nav2/Navigation Plugins\357\203\201.txt" @@ -0,0 +1,38 @@ +Title: Navigation Plugins +URL: https://docs.nav2.org/plugins/index.html#plugins +Section: tuning/index.html +-------------------------------------------------------------------------------- + + +## Behavior-Tree Navigators + + +## Costmap Layers + + +## Costmap Filters + + +## Controllers + + +## Planners + + +## Smoothers + + +## Behaviors + + +## Waypoint Task Executors + + +## Goal Checkers + + +## Progress Checkers + + +## Behavior Tree Nodes + diff --git "a/exported_docs/nav2/Obstacle Layer Parameters\357\203\201.txt" "b/exported_docs/nav2/Obstacle Layer Parameters\357\203\201.txt" new file mode 100644 index 0000000..1edce91 --- /dev/null +++ "b/exported_docs/nav2/Obstacle Layer Parameters\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Obstacle Layer Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/obstacle.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/ObstacleFootprintCritic\357\203\201.txt" "b/exported_docs/nav2/ObstacleFootprintCritic\357\203\201.txt" new file mode 100644 index 0000000..473e783 --- /dev/null +++ "b/exported_docs/nav2/ObstacleFootprintCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: ObstacleFootprintCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/obstacle_footprint.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: ObstacleFootprintCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/Odometry Calibration\357\203\201.txt" "b/exported_docs/nav2/Odometry Calibration\357\203\201.txt" new file mode 100644 index 0000000..4fd853c --- /dev/null +++ "b/exported_docs/nav2/Odometry Calibration\357\203\201.txt" @@ -0,0 +1,88 @@ +Title: Odometry Calibration +URL: https://docs.nav2.org/behavior_trees/trees/odometry_calibration.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/OscillationCritic\357\203\201.txt" "b/exported_docs/nav2/OscillationCritic\357\203\201.txt" new file mode 100644 index 0000000..a5a0936 --- /dev/null +++ "b/exported_docs/nav2/OscillationCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: OscillationCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/oscillation.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: OscillationCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/PathAlignCritic\357\203\201.txt" "b/exported_docs/nav2/PathAlignCritic\357\203\201.txt" new file mode 100644 index 0000000..b7eb5f1 --- /dev/null +++ "b/exported_docs/nav2/PathAlignCritic\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: PathAlignCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/path_align.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: PathAlignCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/PathDistCritic\357\203\201.txt" "b/exported_docs/nav2/PathDistCritic\357\203\201.txt" new file mode 100644 index 0000000..9947cfb --- /dev/null +++ "b/exported_docs/nav2/PathDistCritic\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: PathDistCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/path_dist.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: PathDistCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/PathExpiringTimer\357\203\201.txt" "b/exported_docs/nav2/PathExpiringTimer\357\203\201.txt" new file mode 100644 index 0000000..d647d79 --- /dev/null +++ "b/exported_docs/nav2/PathExpiringTimer\357\203\201.txt" @@ -0,0 +1,21 @@ +Title: PathExpiringTimer +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/PathExpiringTimer.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/PathLongerOnApproach\357\203\201.txt" "b/exported_docs/nav2/PathLongerOnApproach\357\203\201.txt" new file mode 100644 index 0000000..ee35807 --- /dev/null +++ "b/exported_docs/nav2/PathLongerOnApproach\357\203\201.txt" @@ -0,0 +1,28 @@ +Title: PathLongerOnApproach +URL: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/PathLongerOnApproach.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + +``` diff --git "a/exported_docs/nav2/PhotoAtWaypoint\357\203\201.txt" "b/exported_docs/nav2/PhotoAtWaypoint\357\203\201.txt" new file mode 100644 index 0000000..5e27afc --- /dev/null +++ "b/exported_docs/nav2/PhotoAtWaypoint\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: PhotoAtWaypoint +URL: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/photo_at_waypoint.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_waypoint_follower plugin name defined in thewaypoint_task_executor_plugin_idparameter inWaypoint Follower. diff --git "a/exported_docs/nav2/PipelineSequence\357\203\201.txt" "b/exported_docs/nav2/PipelineSequence\357\203\201.txt" new file mode 100644 index 0000000..08ec10d --- /dev/null +++ "b/exported_docs/nav2/PipelineSequence\357\203\201.txt" @@ -0,0 +1,18 @@ +Title: PipelineSequence +URL: https://docs.nav2.org/configuration/packages/bt-plugins/controls/PipelineSequence.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + +``` diff --git "a/exported_docs/nav2/Planner Server\357\203\201.txt" "b/exported_docs/nav2/Planner Server\357\203\201.txt" new file mode 100644 index 0000000..b116448 --- /dev/null +++ "b/exported_docs/nav2/Planner Server\357\203\201.txt" @@ -0,0 +1,59 @@ +Title: Planner Server +URL: https://docs.nav2.org/configuration/packages/configuring-planner-server.html#default-plugins +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Default Plugins +When theplanner_pluginsparameter is not overridden, the following default plugins are loaded: + +## Example + + +Code Examples: + +Language: unknown +File: plugin +``` +planner_server +: +ros__parameters +: +planner_plugins +: +[ +"GridBased" +] +GridBased +: +plugin +: +"nav2_navfn_planner::NavfnPlanner" +# In Iron and older versions, "/" was used instead of "::" +``` + +Language: unknown +File: planner_plugins +``` +planner_server +: +ros__parameters +: +expected_planner_frequency +: +20.0 +planner_plugins +: +[ +'GridBased' +] +GridBased +: +plugin +: +'nav2_navfn_planner::NavfnPlanner' +# In Iron and older versions, "/" was used instead of "::" +``` diff --git "a/exported_docs/nav2/PlannerSelector\357\203\201.txt" "b/exported_docs/nav2/PlannerSelector\357\203\201.txt" new file mode 100644 index 0000000..14a5766 --- /dev/null +++ "b/exported_docs/nav2/PlannerSelector\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: PlannerSelector +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/PlannerSelector.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: transientlocal +``` + +``` diff --git "a/exported_docs/nav2/Plugin Tutorials\357\203\201.txt" "b/exported_docs/nav2/Plugin Tutorials\357\203\201.txt" new file mode 100644 index 0000000..c6ce375 --- /dev/null +++ "b/exported_docs/nav2/Plugin Tutorials\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Plugin Tutorials +URL: https://docs.nav2.org/plugin_tutorials/index.html +Section: plugin_tutorials/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/PoseProgressChecker\357\203\201.txt" "b/exported_docs/nav2/PoseProgressChecker\357\203\201.txt" new file mode 100644 index 0000000..68c8c1d --- /dev/null +++ "b/exported_docs/nav2/PoseProgressChecker\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: PoseProgressChecker +URL: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/pose_progress_checker.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_controller plugin name defined in theprogress_checker_plugin_idparameter inController Server. diff --git "a/exported_docs/nav2/PreferForwardCritic\357\203\201.txt" "b/exported_docs/nav2/PreferForwardCritic\357\203\201.txt" new file mode 100644 index 0000000..98b0184 --- /dev/null +++ "b/exported_docs/nav2/PreferForwardCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: PreferForwardCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/prefer_forward.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: PreferForwardCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/Profiling in ROS 2 _ Nav2\357\203\201.txt" "b/exported_docs/nav2/Profiling in ROS 2 _ Nav2\357\203\201.txt" new file mode 100644 index 0000000..20c3f19 --- /dev/null +++ "b/exported_docs/nav2/Profiling in ROS 2 _ Nav2\357\203\201.txt" @@ -0,0 +1,209 @@ +Title: Profiling in ROS 2 / Nav2 +URL: https://docs.nav2.org/tutorials/docs/get_profile.html#overview +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This document explains one method for profiling applications in ROS 2 / Nav2. The aim of profiling is to generate files that can be analyzed to see where compute time and resources are spent during the execution of a program. This can be useful to determine where the bottlenecks in your program exist and where things might be able to be improved. +The following steps show ROS 2 users how to modify the Nav2 stack to get profiling information about a particular server / algorithm when they encounter a situation they’d like to understand better. This tutorial applies to both simulated and physical robots. + +## Preliminaries +This tutorial makes use of two tools, callgrind from theValgrindset of tools andkcachegrind. Valgrind is used to get the profiling information about the program and kcachegrind is the visualization engine used to interpret this information to do useful work. +Thus, we must install them. +More information can be found in theValgrind manualincluding additional valgrind arguments that can be used to specify more information. +Generally speaking, to use valgrind we need to compile with debugging information. This can be done by passing-gas a compiling option or compileCMAKE_BUILD_TYPEasDebugorRelWithDebInfo. Then, we run our program using valgrind to capture the run-time statistics for later analysis. These are stored incallgrind.out.XXXfiles, where the suffix is the PID of the process. kcachegrind is used to visualize and analyze the results of the program execution. + +## Profile from a Node +As in our generic example, for a given node, we need to compile with debug flags to capture the information for profiling with Valgrind. This can be done easily from the commandline. Note that we use--packages-selectto only compile with this flag for the packages we want to profile nodes within. +Optionally, you may add the following line to theCMakeLists.txtof the package you’re looking to profile. This may be preferable when you have a workspace with many packages but would like to only compile a subset with debug information using a singlecolconbuildinvocation. +It is important that this should be added to both the host server and plugin packages(s) if you would like the results of a plugin’s run-time profile. +After either compiling method, this node should be run in its own terminal to isolate it from the rest of your system. Thus, this should not be composed in the same process as other nodes. To run a ROS 2 node with valgrind, this can be done from the commandline via: +An example of this might be used for profiling the controller server with a particular controller plugin loaded. Bothnav2_controllerand the plugin package of interest are compiled with debug flags. In the example below, we are running a ROS 2 node with remapped topics and a path to its parameter file: +Once sufficient data has been collected, cleanly exit the process with Control+C. + +## Profile from a Launch File +Just as in the Node example, we must also compile with debug flags when profiling a node from launch. We can complete the same valgrind call as from the commandline as within a launch file using launch prefixes. +As our example before, this is how we’d launch thecontroller_servernode from inside a launch file. +Note that just like before, we should isolate this process from others. So this should not be run with any other nodes in this launch file nor use node composition when profiling a particular node. +Once sufficient data has been collected, cleanly exit the process with Control+C. + +## From Nav2 Bringup +Because Nav2 bringup has more than one node per launch file (and in the caseuse_composition=true, more than one per process), it is necessary to separate out a particular node that you’re interested in profiling from the rest of the system. As previously described, once they’re isolated in either a launch file or as a node to be launched on the commandline, they can easily be run to collect the callgrind information. +The steps within Nav2 are as follows: +It is important that the profiler node is launched before Nav2 so that it can take the signals from the lifecycle manager to transition up. + +## Interpreting Results +Once you have yourcallgrindresults, regardless of if you did it through a node, launch file, Nav2, or elsewhere, now we can analyze the results from the profiler to identify bottlenecks or potential areas of improvement. Usingkcachegrind: +This should open a window looking like below. The left side shows all of the calls and their relative percentages of compute time they and their children functions utilized. +If you select the top level entry on the left sidebar, then select “Call Graph” at the bottom of the right workspace, it should show you a call graph of where the compute time was spent as a graph of method calls. This can be exceptionally helpful to find the methods where the most time is spent. + +Code Examples: + +Language: unknown +File: kcachegrind +``` +sudo +apt +install +valgrind +kcachegrind + +``` + +Language: unknown +File: callgrind.out.XXX +``` +# CMakeLists.txt +add_compile_options +( +-g +) +``` + +Language: unknown +File: callgrind.out.XXX +``` +cmake +-DCMAKE_BUILD_TYPE += +RelWithDebInfo + +``` + +Language: unknown +File: callgrind.out.XXX +``` +valgrind +--tool += +callgrind +[ +your-program +] +[ +program +options +] + + +kcachegrind +callgrind.out.XXX + +``` + +Language: unknown +File: --packages-select +``` +colcon +build +--packages-select + +--cmake-args +-DCMAKE_BUILD_TYPE += +RelWithDebInfo + +``` + +Language: unknown +File: colconbuild +``` +add_compile_options +( +-pg +) +``` + +Language: unknown +File: colconbuild +``` +ros2 +run +--prefix +'valgrind --tool=callgrind' + + +--all-other-launch +arguments + +``` + +Language: unknown +File: nav2_controller +``` +ros2 +run +--prefix +'valgrind --tool=callgrind' +nav2_controller +controller_server +--ros-args +-r +__node: += +controller_server +-r +cmd_vel: += +cmd_vel_nav +--params-file +/path/to/nav2_bringup/params/nav2_params.yaml + +``` + +Language: unknown +File: controller_server +``` +start_controller_server_node += +Node +( +parameters += +[ +get_package_share_directory +( +"nav2_bringup" +) ++ +'/params/nav2_params.yaml' +, +{ +'use_sim_time' +: +use_sim_time +} +], +package += +'nav2_controller' +, +executable += +'controller_server' +, +name += +'controller_server' +, +prefix += +[ +'xterm -e valgrind --tool=callgrind' +], +output += +'screen' +) +``` + +Language: unknown +File: kcachegrind +``` +kcachegrind +callgrind.out.XXX + +``` diff --git "a/exported_docs/nav2/ProgressCheckerSelector\357\203\201.txt" "b/exported_docs/nav2/ProgressCheckerSelector\357\203\201.txt" new file mode 100644 index 0000000..3137170 --- /dev/null +++ "b/exported_docs/nav2/ProgressCheckerSelector\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: ProgressCheckerSelector +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ProgressCheckerSelector.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: transientlocal +``` + +``` diff --git "a/exported_docs/nav2/Publisher\357\203\201.txt" "b/exported_docs/nav2/Publisher\357\203\201.txt" new file mode 100644 index 0000000..c5d370f --- /dev/null +++ "b/exported_docs/nav2/Publisher\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Publisher +URL: https://docs.nav2.org/configuration/packages/dwb-params/visualization.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. diff --git "a/exported_docs/nav2/Range Sensor Parameters\357\203\201.txt" "b/exported_docs/nav2/Range Sensor Parameters\357\203\201.txt" new file mode 100644 index 0000000..0956e7d --- /dev/null +++ "b/exported_docs/nav2/Range Sensor Parameters\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Range Sensor Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/range.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/RateController\357\203\201.txt" "b/exported_docs/nav2/RateController\357\203\201.txt" new file mode 100644 index 0000000..97ea552 --- /dev/null +++ "b/exported_docs/nav2/RateController\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: RateController +URL: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/RateController.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: GoalReached +``` + + + +``` diff --git "a/exported_docs/nav2/RecoveryNode\357\203\201.txt" "b/exported_docs/nav2/RecoveryNode\357\203\201.txt" new file mode 100644 index 0000000..f7ccc06 --- /dev/null +++ "b/exported_docs/nav2/RecoveryNode\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: RecoveryNode +URL: https://docs.nav2.org/configuration/packages/bt-plugins/controls/RecoveryNode.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + +``` diff --git "a/exported_docs/nav2/Regulated Pure Pursuit\357\203\201.txt" "b/exported_docs/nav2/Regulated Pure Pursuit\357\203\201.txt" new file mode 100644 index 0000000..9f967a8 --- /dev/null +++ "b/exported_docs/nav2/Regulated Pure Pursuit\357\203\201.txt" @@ -0,0 +1,152 @@ +Title: Regulated Pure Pursuit +URL: https://docs.nav2.org/configuration/packages/configuring-regulated-pp.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Regulated Pure Pursuit Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: true +``` +controller_server +: +ros__parameters +: +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +goal_checker_plugins +: +[ +"goal_checker" +] +controller_plugins +: +[ +"FollowPath" +] +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +required_movement_radius +: +0.5 +movement_time_allowance +: +10.0 +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +stateful +: +True +FollowPath +: +plugin +: +"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController" +desired_linear_vel +: +0.5 +lookahead_dist +: +0.6 +min_lookahead_dist +: +0.3 +max_lookahead_dist +: +0.9 +lookahead_time +: +1.5 +rotate_to_heading_angular_vel +: +1.8 +transform_tolerance +: +0.1 +use_velocity_scaled_lookahead_dist +: +false +min_approach_linear_velocity +: +0.05 +approach_velocity_scaling_dist +: +0.6 +use_collision_detection +: +true +max_allowed_time_to_collision_up_to_carrot +: +1.0 +use_regulated_linear_velocity_scaling +: +true +use_fixed_curvature_lookahead +: +false +curvature_lookahead_dist +: +0.25 +use_cost_regulated_linear_velocity_scaling +: +false +regulated_linear_scaling_min_radius +: +0.9 +regulated_linear_scaling_min_speed +: +0.25 +use_rotate_to_heading +: +true +allow_reversing +: +false +rotate_to_heading_min_angle +: +0.785 +max_angular_accel +: +3.2 +max_robot_pose_search_dist +: +10.0 +``` diff --git "a/exported_docs/nav2/ReinitializeGlobalLocalization\357\203\201.txt" "b/exported_docs/nav2/ReinitializeGlobalLocalization\357\203\201.txt" new file mode 100644 index 0000000..28f28d2 --- /dev/null +++ "b/exported_docs/nav2/ReinitializeGlobalLocalization\357\203\201.txt" @@ -0,0 +1,22 @@ +Title: ReinitializeGlobalLocalization +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/ReinitializeGlobalLocalization.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/Related Projects\357\203\201.txt" "b/exported_docs/nav2/Related Projects\357\203\201.txt" new file mode 100644 index 0000000..f987e96 --- /dev/null +++ "b/exported_docs/nav2/Related Projects\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Related Projects +URL: https://docs.nav2.org/about/related_projects.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/RemoveInCollisionGoals\357\203\201.txt" "b/exported_docs/nav2/RemoveInCollisionGoals\357\203\201.txt" new file mode 100644 index 0000000..0e07dc3 --- /dev/null +++ "b/exported_docs/nav2/RemoveInCollisionGoals\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: RemoveInCollisionGoals +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/RemoveInCollisionGoals.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_footprint=false +``` + +``` diff --git "a/exported_docs/nav2/RemovePassedGoals\357\203\201.txt" "b/exported_docs/nav2/RemovePassedGoals\357\203\201.txt" new file mode 100644 index 0000000..977be2a --- /dev/null +++ "b/exported_docs/nav2/RemovePassedGoals\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: RemovePassedGoals +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/RemovePassedGoals.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: ComputePathThroughPoses +``` + +``` diff --git "a/exported_docs/nav2/Roadmaps\357\203\201.txt" "b/exported_docs/nav2/Roadmaps\357\203\201.txt" new file mode 100644 index 0000000..d673456 --- /dev/null +++ "b/exported_docs/nav2/Roadmaps\357\203\201.txt" @@ -0,0 +1,14 @@ +Title: Roadmaps +URL: https://docs.nav2.org/roadmap/roadmap.html#jazzy-roadmap +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Jazzy Roadmap + + +## Iron Roadmap + + +## Humble Roadmap + diff --git "a/exported_docs/nav2/Robots Using\357\203\201.txt" "b/exported_docs/nav2/Robots Using\357\203\201.txt" new file mode 100644 index 0000000..d789eb9 --- /dev/null +++ "b/exported_docs/nav2/Robots Using\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Robots Using +URL: https://docs.nav2.org/about/robots.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/RotateToGoalCritic\357\203\201.txt" "b/exported_docs/nav2/RotateToGoalCritic\357\203\201.txt" new file mode 100644 index 0000000..fca6047 --- /dev/null +++ "b/exported_docs/nav2/RotateToGoalCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: RotateToGoalCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/rotate_to_goal.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: RotateToGoalCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/Rotation Shim Controller\357\203\201.txt" "b/exported_docs/nav2/Rotation Shim Controller\357\203\201.txt" new file mode 100644 index 0000000..70a54e3 --- /dev/null +++ "b/exported_docs/nav2/Rotation Shim Controller\357\203\201.txt" @@ -0,0 +1,106 @@ +Title: Rotation Shim Controller +URL: https://docs.nav2.org/configuration/packages/configuring-rotation-shim-controller.html#configuring-rotation-shim +Section: tuning/index.html +-------------------------------------------------------------------------------- + + +## Rotation Shim Controller Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: README +``` +controller_server +: +ros__parameters +: +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +goal_checker_plugins +: +[ +"goal_checker" +] +controller_plugins +: +[ +"FollowPath" +] +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +required_movement_radius +: +0.5 +movement_time_allowance +: +10.0 +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +stateful +: +True +FollowPath +: +plugin +: +"nav2_rotation_shim_controller::RotationShimController" +primary_controller +: +"nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController" +angular_dist_threshold +: +0.785 +forward_sampling_distance +: +0.5 +rotate_to_heading_angular_vel +: +1.8 +max_angular_accel +: +3.2 +simulate_ahead_time +: +1.0 +rotate_to_goal_heading +: +false +# Primary controller params can be placed here below +# ... +``` diff --git "a/exported_docs/nav2/RoundRobin\357\203\201.txt" "b/exported_docs/nav2/RoundRobin\357\203\201.txt" new file mode 100644 index 0000000..0b74759 --- /dev/null +++ "b/exported_docs/nav2/RoundRobin\357\203\201.txt" @@ -0,0 +1,18 @@ +Title: RoundRobin +URL: https://docs.nav2.org/configuration/packages/bt-plugins/controls/RoundRobin.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + +``` diff --git "a/exported_docs/nav2/Savitzky-Golay Smoother\357\203\201.txt" "b/exported_docs/nav2/Savitzky-Golay Smoother\357\203\201.txt" new file mode 100644 index 0000000..cfe3aab --- /dev/null +++ "b/exported_docs/nav2/Savitzky-Golay Smoother\357\203\201.txt" @@ -0,0 +1,50 @@ +Title: Savitzky-Golay Smoother +URL: https://docs.nav2.org/configuration/packages/configuring-savitzky-golay-smoother.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Savitzky-Golay Smoother Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: refinement_num +``` +smoother_server +: +ros__parameters +: +costmap_topic +: +global_costmap/costmap_raw +footprint_topic +: +global_costmap/published_footprint +robot_base_frame +: +base_link +transform_timeout +: +0.1 +smoother_plugins +: +[ +"savitzky_golay_smoother" +] +savitzky_golay_smoother +: +plugin +: +"nav2_smoother::SavitzkyGolaySmoother" +do_refinement +: +True +refinement_num +: +2 +``` diff --git "a/exported_docs/nav2/Setting Up Navigation Plugins\357\203\201.txt" "b/exported_docs/nav2/Setting Up Navigation Plugins\357\203\201.txt" new file mode 100644 index 0000000..d9b09f2 --- /dev/null +++ "b/exported_docs/nav2/Setting Up Navigation Plugins\357\203\201.txt" @@ -0,0 +1,84 @@ +Title: Setting Up Navigation Plugins +URL: https://docs.nav2.org/setup_guides/algorithm/select_algorithm.html#select-algorithm +Section: tuning/index.html +-------------------------------------------------------------------------------- + + +## Planner and Controller Servers +Navigation algorithms are implemented in Nav2 through the use of plugins running on ROS action servers - the planner, controller and behavior servers (among others). For this section, we discuss the planner and controller servers, which are the heart of the navigation stack. These servers may implement one or more algorithm plugins each with its own configuration tailored for a specific action or robot state. This guide will highlight the different algorithms based on the type of robot and environment the robot is deployed in. This guide will not cover behaviors, smoothers, etc as those are dependent on application and not hardware/environment to offer generalized advice. +The planner server is responsible for implementing algorithms that compute the robot’s path. For example, one plugin can be configured to compute a simple shortest path between two relatively near locations while another plugin computes for a path to locations that cover the entire robot environment. +The controller server generates the appropriate control efforts needed for a robot to complete a task in its local environment. These tasks include but are not limited to: following a path generated by the planner server, avoiding dynamic obstacles along this path, and even charging at a docking station. +As mentioned before, the planner and controller servers host a map of one or multiple plugins wherein a certain plugin will be used for a certain environment, scenario, or task. For instance, the controller server can have a plugin for following a path when in long corridors to stay in the middle of the aisle, and then another plugin for avoiding dynamic obstacles in a crowded place. Selecting which planning algorithm to execute based on the robot’s task can be done through the behavior tree of your navigation system or application server. + +## Selecting the Algorithm Plugins +In this section, we discuss some of the available algorithm plugins for the planner and controller servers. We also discuss the purpose of each algorithm, and for which type of robot they are recommended to be used. Lastly, we show some sample yaml configuration that specifies the plugin to be used for each server. + +## Planner Server +The algorithm plugins for the planner server find the robot’s path using a representation of its environment captured by its different sensors. Some of these algorithms operate by searching through the environment’s grid space while others expand the robot’s possible states while accounting for path feasibility. +As mentioned, the planner server may utilize plugins that work on the grid space such as theNavFnPlanner,SmacPlanner2D, andThetaStarPlanner. TheNavFn planneris a navigation function planner that uses either Dijkstra or A*. Next, theSmac 2D plannerimplements a 2D A* algorithm using 4 or 8 connected neighborhoods with a smoother and multi-resolution query. Lastly, theTheta Star planneris an implementation of Theta* using either line of sight to create non-discretely oriented path segments. +One issue you may encounter when using algorithms that work on the grid space is that there is no guarantee that a drivable path can be generated for any type of robot. For example, it is not guaranteed that theNavFnPlannercan plan a feasible path for a non-circular robot in a tight space since it uses the circular footprint of a robot (by approximating the robot’s largest cross-sectional radius) and checks for collisions per costmap grid cell. In addition, these algorithms are also not suitable for ackermann and legged robots since they have turning constraints. That being said, these plugins are best used on robots that can drive in any direction or rotate safely in place, such ascircular differential and circular omnidirectionalrobots. +Another planner plugin is theSmac Hybrid-A* plannerthat supportsarbitrary shaped ackermann and leggedrobots. It is a highly optimized and fully reconfigurable Hybrid-A* implementation supporting Dubin and Reeds-Shepp motion models. This algorithm expands the robot’s candidate paths while considering the robot’s minimum turning radius constraint and the robot’s full footprint for collision avoidance. Thus, this plugin is suitable for arbitrary shaped robots that require full footprint collision checking. It may also be used for high-speed robots that must be navigated carefully to not flip over, skid, or dump load at high speeds. +There is also theSmacLatticeplannerplugin which is based on a State Lattice planner. This plugin functions by expanding the robot state space while ensuring the path complies with the robot’s kinematic constraints. The algorithm provides minimum control sets which allows it to supportdifferential, omnidirectional, and ackermannvehicles of any shape and size with minimal reconfiguration. + +## Summary + + +## Example Configuration +An example configuration of the planner server is shown above. Theplanner_pluginsparameter accepts a list of mapped planner plugin names. For each plugin namespace defined inplanner_plugins(GridBasedin our example), we specify the type of plugin to be loaded in thepluginparameter. Additional configurations must then be specified in this namespace based on the algorithm to be used. Please see theConfiguration Guidefor more details. + +## Controller Server +The default controller plugin is theDWB controller. It implements a modified Dynamic Window Approach (DWA) algorithm with configurable plugins to compute the control commands for the robot. This controller makes use of aTrajectoryGeneratorpluginthat generates the set of possible trajectories. These are then evaluated by one or moreCriticplugins, each of which may give a different score based on how they are configured. The sum of the scores from theseCriticpluginsdetermine the overall score of a trajectory. The best scoring trajectory then determines the output command velocity. +TheDWBcontrollercan be used oncircular or non-circular differential, and circular or non-circular omnidirectionalrobots. It may also be configured forackerman and leggedrobots if it is given aTrajectoryGenerationpluginthat produces a set of possible trajectories that considers the robot’s minimum curvature constraint. +Next example of a controller server plugin is theTEB controllerwhich is an MPC time optimal controller. It implements the Timed Elastic Band (TEB) approach which optimizes the robot’s trajectory based on its execution time, distance from obstacles, and feasibility with respect to the robot’s kinematic constraints. This controller can be used ondifferential, omnidirectional, ackermann, and leggedrobots. +Another example for this section is theRegulated Pure Pursuit controller (RPP). This controller implements a variant of the pure pursuit algorithm with added regulation heuristic functions to manage collision and velocity constraints. This variation is implemented to target the needs of service or industrial robots and is suitable for use withdifferential, ackermann, and leggedrobots. +The last example is theVector Pursuit Controller. It implements theVector Pursuit algorithmand calculates the command velocity using screw theory. This controller is suitable for high speed path tracking and sharp turns or when computation resources are limited. It can be used fordifferential, ackermann, and leggedrobots. + +## Summary +All of these algorithms work for both circular and non-circular robots. + +## Example Configuration +Shown above is a sample basic configuration of the controller server. The list of mapped names for controller plugins are defined in thecontroller_pluginsparameter. Similar to the planner server, each namespace defined in thecontroller_plugins(FollowPathin our example) must define the type of plugin it will use in thepluginparameter. Additional configurations must also be made for the selected algorithm in the namespace. Please see theConfiguration Guidefor more details. + +## Conclusion +In this tutorial, we have discussed the roles and configuration of Nav2’s planner and controller servers. To summarize, these servers host a map of one or more algorithm plugins which are selected depending on your robot’s structure and surroundings. We also described a few of the available plugins for the planner and controller servers to help you identify which plugins are suitable for your robot. Lastly, we also provided some simple configuration examples to show how these plugins are instantiated on the servers. You can refer to the configuration guide of the algorithm plugin you will select for more details on its configuration parameters. + +Code Examples: + +Language: unknown +File: SmacLatticeplanner +``` +planner_server +: +ros__parameters +: +planner_plugins +: +[ +'GridBased' +] +GridBased +: +plugin +: +'nav2_navfn_planner::NavfnPlanner' +# In Iron and older versions, "/" was used instead of "::" +``` + +Language: unknown +File: TrajectoryGenerationplugin +``` +controller_server +: +ros__parameters +: +controller_plugins +: +[ +"FollowPath" +] +FollowPath +: +plugin +: +"dwb_core::DWBLocalPlanner" +``` diff --git "a/exported_docs/nav2/Setting Up Odometry\357\203\201.txt" "b/exported_docs/nav2/Setting Up Odometry\357\203\201.txt" new file mode 100644 index 0000000..cd1817c --- /dev/null +++ "b/exported_docs/nav2/Setting Up Odometry\357\203\201.txt" @@ -0,0 +1,1207 @@ +Title: Setting Up Odometry +URL: https://docs.nav2.org/setup_guides/odom/setup_odom.html#setup-and-prerequisites +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Odometry Introduction +The odometry system provides a locally accurate estimate of a robot’s pose and velocity based on its motion. The odometry information can be obtained from various sources such as IMU, LIDAR, RADAR, VIO, and wheel encoders. One thing to note is that IMUs drift over time while wheel encoders drift over distance traveled, thus they are often used together to counter each other’s negative characteristics. +Theodomframe and the transformation associated with it use a robot’s odometry system to publish localization information that is continuous but becomes less accurate over time or distance (depending on the sensor modalities and drift). In spite of this, the information can still be used by the robot to navigate its immediate vicinity (e.g collision avoidance). To obtain consistently accurate odometry information over time, themapframe provides globally accurate information that is used to correct theodomframe. +As discussed in the previous guides and inREP 105, theodomframe is connected to the rest of the system and Nav2 through theodom=>base_linktransform. This transform is published by a tf2 broadcaster or by frameworks such asrobot_localization, which also provide additional functionalities. We will be talking more aboutrobot_localizationin a following section. +In addition to the requiredodom=>base_linktransform, Nav2 also requires the publishing ofnav_msgs/Odometrymessage because this message provides the velocity information of the robot. In detail, thenav_msgs/Odometrymessage contains the following information: +This message tells us the estimates for the pose and velocity of the robot. Theheadermessage provides the timestamped data in a given coordinate frame. Theposemessage provides the position and orientation of the robot relative to the frame specified inheader.frame_id. Thetwistmessage gives the linear and angular velocity relative to the frame defined inchild_frame_id. + +## Setting Up Odometry on your Robot +Setting up the odometry system for Nav2 for your physical robot depends a lot on which odometry sensors are available with your robot. Due to the large number of configurations your robot may have, specific setup instructions will not be within the scope of this tutorial. Instead, we will provide some basic examples and useful resources to help you configure your robot for Nav2. +To start, we will use an example of a robot with wheel encoders as its odometry source. Note that wheel encoders are not required for Nav2 but it is common in most setups. The goal in setting up the odometry is to compute the odometry information and publish thenav_msgs/Odometrymessage andodom=>base_linktransform over ROS 2. To calculate this information, you will need to setup some code that will translate wheel encoder information into odometry information, similar to the snippet below: +Theright_wheel_est_velandleft_wheel_est_velare the estimated velocities of the right and left wheels respectively, and thewheelseparationis the distance between the wheels. The values ofright_wheel_est_velandleft_wheel_est_velcan be obtained by simply getting the changes in the positions of the wheel joints over time. This information can then be used to publish the Nav2 requirements. A basic example on how to do this can be found in the Navigation documentation on odometrylocated here +An alternative to manually publishing this information that we recommend is through theros2_controlframework. Theros2_controlframework contains various packages for real-time control of robots in ROS 2. For wheel encoders,ros2_controlhas adiff_drive_controller(differential drive controller) under theros2_controllerpackage. Thediff_drive_controllertakes in thegeometry_msgs/Twistmessages published oncmd_veltopic, computes odometry information, and publishesnav_msgs/Odometrymessages onodomtopic. Other packages that deal with different kind of sensors are also available inros2_control. +For other types of sensors such as IMU, VIO, etc, their respective ROS drivers should have documentation on how publish the odometry information. Keep in mind that Nav2 requires thenav_msgs/Odometrymessage andodom=>base_linktransforms to be published and this should be your goal when setting up your odometry system. + +## Simulating an Odometry System using Gazebo +In this section, we will be using Gazebo to simulate the odometry system ofsam_bot, the robot that we built in the previous section of this tutorial series. You may go through that guide first or grab thecomplete source here. +As an overview for this section, we will first setup Gazebo and the necessary packages required to make it work with ROS 2. Next, we will be adding Gazebo plugins, which simulate an IMU sensor and a differential drive odometry system, in order to publishsensor_msgs/Imuandnav_msgs/Odometrymessages respectively. Lastly, we will spawnsam_botin a Gazebo environment and verify the publishedsensor_msgs/Imuandnav_msgs/Odometrymessages over ROS 2. + +## Setup and Prerequisites +Gazebois a 3D simulator that allows us to observe how our virtual robot will function in a simulated environment. To start using Gazebo with ROS 2, follow the installation instructions in theGazebo Installation Documentation. +We also need to install thegazebo_ros_pkgspackage to simulate odometry and control the robot with ROS 2 in Gazebo: +You can test if you have successfully set up your ROS 2 and Gazebo environments by following the instructionsgiven here. +Note that we describedsam_botusing URDF. However, Gazebo usesSimulation Description Format (SDF)to describe a robot in its simulated environment. Fortunately, Gazebo automatically translates compatible URDF files into SDF. The main requirement for the URDF to be compatible with Gazebo is to have anelement within eachelement. This requirement is already satisfied in the URDF file ofsam_bot, so it can already be used in Gazebo. + +## Adding Gazebo Plugins to a URDF +We will now add the IMU sensor and the differential drive plugins of Gazebo to our URDF. For an overview of the different plugins available in Gazebo, have a look atTutorial: Using Gazebo plugins with ROS. +For our robot, we will be using theGazeboRosImuSensorwhich is a SensorPlugin. A SensorPlugin must be attached to a link, thus we will create animu_linkto which the IMU sensor will be attached. This link will be referenced under theelement. Next, we will set/demo/imuas the topic to which the IMU will be publishing its information, and we will comply withREP145by settinginitalOrientationAsReferencetofalse. We will also add some noise to the sensor configuration using Gazebo’ssensor noise model. +Now, we will set up our IMU sensor plugin according to the description above by adding the following lines before theline in our URDF: +Now, let us add the differential drive ModelPlugin. We will configure the plugin such thatnav_msgs/Odometrymessages are published on the/demo/odomtopic. The joints of the left and right wheels will be set to the wheel joints ofsam_bot. The wheel separation and wheel diameter are set according to the values of the defined values ofwheel_ygapandwheel_radiusrespectively. +To include this plugin in our URDF, add the following lines after thetag of the IMU plugin: + +## Launch and Build Files +We will now edit our launch file,launch/display.launch.py, to spawnsam_botin Gazebo. Since we will be simulating our robot, we can remove the GUI for the joint state publisher by deleting the following lines inside thegenerate_launch_description(): +Remove the followingguiparam: +Remove the condition and parameters. Add arguments to thejoint_state_publisher_node: +Next, openpackage.xmland delete the line: +To launch Gazebo, add the following before thejoint_state_publisher_node,line indisplay.launch.py +We will now add a node that spawnssam_botin Gazebo. Openlaunch/display.launch.pyagain and paste the following lines before thereturnlaunch.LaunchDescription([line. +Then add the linespawn_entity,before therviz_nodeline, as shown below. + +## Build, Run and Verification +Let us run our package to check if the/demo/imuand/demo/odomtopics are active in the system. +Navigate to the root of the project and execute the following lines: +Gazebo should launch and you should see a 3D model ofsam_bot: +To see the active topics in the system, open a new terminal and execute: +You should see/demo/imuand/demo/odomin the list of topics. +To see more information about the topics, execute: +You should see an output similar to below: +Observe that the/demo/imutopic publishessensor_msgs/Imutype messages while the/demo/odomtopic publishesnav_msgs/Odometrytype messages. The information being published on these topics come from the gazebo simulation of the IMU sensor and the differential drive respectively. Also note that both topics currently have no subscribers. In the next section, we will create arobot_localizationnode that will subscribe to these two topics. It will then use the messages published on both topics to provide a fused, locally accurate and smooth odometry information for Nav2. + +## Robot Localization Demo +Therobot_localizationpackage is used to provide a fused and locally accurate smooth odometry information from the data provided byNodometry sensor inputs. These information can be provided to the package throughnav_msgs/Odometry,sensor_msgs/Imu,geometry_msgs/PoseWithCovarianceStamped, andgeometry_msgs/TwistWithCovarianceStampedmessages. +A usual robot setup consists of at least the wheel encoders and IMU as its odometry sensor sources. When multiple sources are provided torobot_localization, it is able to fuse the odometry information given by the sensors through the use of state estimation nodes. These nodes make use of either an Extended Kalman filter (ekf_node) or an Unscented Kalman Filter (ukf_node) to implement this fusion. In addition, the package also implements anavsat_transform_nodewhich transforms geographic coordinates into the robot’s world frame when working with GPS. +Fused sensor data is published by therobot_localizationpackage through theodometry/filteredand theaccel/filteredtopics, if enabled in its configuration. In addition, it can also publish theodom=>base_linktransform on the/tftopic. +If your robot is only able to provide one odometry source, the use ofrobot_localizationwould have minimal effects aside from smoothing. In this case, an alternative approach is to publish transforms through a tf2 broadcaster in your single source of odometry node. Nevertheless, you can still opt to userobot_localizationto publish the transforms and some smoothing properties may still be observed in the output. +For the rest of this section, we will show how to userobot_localizationto fuse the sensors ofsam_bot. It will use thesensor_msgs/Imumessages published on/demo/Imuand thenav_msgs/Odometrymessage published on/demo/odomand then it will publish data onodometry/filtered,accel/filtered, and/tftopics. + +## Configuring Robot Localization +Let us now configure therobot_localizationpackage to use an Extended Kalman Filter (ekf_node) to fuse odometry information and publish theodom=>base_linktransform. +First, install therobot_localizationpackage using your machines package manager or by executing the following command: +Next, we specify the parameters of theekf_nodeusing a YAML file. Create a directory namedconfigat the root of your project and create a file namedekf.yaml. Copy the following lines of code into yourekf.yamlfile. +In this configuration, we defined the parameter values offrequency,two_d_mode,publish_acceleration,publish_tf,map_frame,odom_frame,base_link_frame, andworld_frame. For more information on the other parameters you can modify, seeParameters of state estimation nodes, and a sampleefk.yamlcan be foundhere. +To add a sensor input to theekf_filter_node, add the next number in the sequence to its base name (odom, imu, pose, twist). In our case, we have onenav_msgs/Odometryand onesensor_msgs/Imuas inputs to the filter, thus we useodom0andimu0. We set the value ofodom0todemo/odom, which is the topic that publishes thenav_msgs/Odometry. Similarly, we set the value ofimu0to the topic that publishessensor_msgs/Imu, which isdemo/imu. +You can specify which values from a sensor are to be used by the filter using the_configparameter. The order of the values of this parameter is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. In our example, we set everything inodom0_configtofalseexcept the 1st, 2nd, 3rd, and 12th entries, which means the filter will only use the x, y, z, and the vyaw values ofodom0. +In theimu0_configmatrix, you’ll notice that only roll, pitch, and yaw are used. Typical mobile robot-grade IMUs will also provide angular velocities and linear accelerations. Forrobot_localizationto work properly, you should not fuse in multiple fields that are derivative of each other. Since angular velocity is fused internally to the IMU to provide the roll, pitch and yaw estimates, we should not fuse in the angular velocities used to derive that information. We also do not fuse in angular velocity due to the noisy characteristics it has when not using exceptionally high quality (and expensive) IMUs. + +## Launch and Build Files +Now, let us add theekf_nodeinto the launch file. Openlaunch/display.launch.pyand paste the following lines before thereturnlaunch.LaunchDescription([line. +Next, add the following launch arguments within thereturnlaunch.LaunchDescription([block. +Lastly, addrobot_localization_node,above therviz_nodeline to launch the robot localization node. +Next, we need to add therobot_localizationdependency to our package definition. Openpackage.xmland add the following line below the lasttag. +Lastly, openCMakeLists.txtand append theconfigdirectory inside theinstall(DIRECTORY...), as shown in the snippet below. + +## Build, Run and Verification +Let us now build and run our package. Navigate to the root of the project and execute the following lines: +Gazebo and RVIZ should launch. In the RVIZ window, you should see the model and TF frames ofsam_bot: +Next, let us verify that theodometry/filtered,accel/filtered, and/tftopics are active in the system. Open a new terminal and execute: +You should seeodometry/filtered,accel/filtered, and/tfin the list of the topics. +You can also check the subscriber count of these topics again by executing: +You should see that/demo/imuand/demo/odomnow both have 1 subscriber each. +To verify that theekf_filter_nodeare the subscribers of these topics, execute: +You should see an output as shown below. +From the output above, we can see that theekf_filter_nodeis subscribed to/demo/imuand/demo/odom. We can also see that theekf_filter_nodepublishes on theodometry/filtered,accel/filtered, and/tftopics. +You may also verify thatrobot_localizationis publishing theodom=>base_linktransform by using the tf2_echo utility. Run the following command in a separate command line terminal: +You should see a continuous output similar to what is shown below. + +## Conclusion +In this guide, we have discussed the messages and transforms that are expected by Nav2 from the odometry system. We have seen how to set up an odometry system and how to verify the published messages. We also have discussed how multiple odometry sensors can be used to provide a filtered and smoothed odometry usingrobot_localization. We have also checked if theodom=>base_linktransform is being published correctly byrobot_localization. + +Code Examples: + +Language: unknown +File: nav_msgs/Odometry +``` +# This represents estimates of position and velocity in free space. +# The pose in this message should be specified in the coordinate frame given by header.frame_id +# The twist in this message should be specified in the coordinate frame given by the child_frame_id +# Includes the frame id of the pose parent. + +std_msgs/Header +header + + +# Frame id the pose is pointing at. The twist is in this coordinate frame. + +string +child_frame_id + + +# Estimated pose that is typically relative to a fixed world frame. + +geometry_msgs/PoseWithCovariance +pose + + +# Estimated linear and angular velocity relative to child_frame_id. + +geometry_msgs/TwistWithCovariance +twist + +``` + +Language: unknown +File: base_link +``` +linear += +( +right_wheel_est_vel ++ +left_wheel_est_vel +) +/ +2 +angular += +( +right_wheel_est_vel +- +left_wheel_est_vel +) +/ +wheel_separation +; +``` + +Language: unknown +File: gazebo_ros_pkgs +``` +sudo +apt +install +ros--gazebo-ros-pkgs + +``` + +Language: unknown +File: +``` +132 + +133 + +134 + +135 + +136 + +137 + +138 +139 + +140 + +141 + +142 + +143 + +144 +145 + +146 + +147 +148 + +149 + +150 + +151 + +152 + +153 +154 + +155 + +156 + +157 + +158 + +/demo + +159 + +~/out:=imu + +160 + +161 + +false + +162 + +163 + +true + +164 + +100 + +165 + +true + +166 + +167 + +168 + +169 + +170 + +0.0 + +171 + +2e-4 + +172 + +0.0000075 + +173 + +0.0000008 + +174 + +175 + +176 + +177 + +178 + +0.0 + +179 + +2e-4 + +180 + +0.0000075 + +181 + +0.0000008 + +182 + +183 + +184 + +185 + +186 + +0.0 + +187 + +2e-4 + +188 + +0.0000075 + +189 + +0.0000008 + +190 + +191 + +192 + +193 + +194 + +195 + +196 + +0.0 + +197 + +1.7e-2 + +198 + +0.1 + +199 + +0.001 + +200 + +201 + +202 + +203 + +204 + +0.0 + +205 + +1.7e-2 + +206 + +0.1 + +207 + +0.001 + +208 + +209 + +210 + +211 + +212 + +0.0 + +213 + +1.7e-2 + +214 + +0.1 + +215 + +0.001 + +216 + +217 + +218 + +219 + +220 + +221 + +``` + +Language: unknown +File: +``` +223 + +224 + +225 + +226 + +/demo + +227 + +228 +229 + +230 + +drivewhl_l_joint + +231 + +drivewhl_r_joint + +232 +233 + +234 + +0.4 + +235 + +0.2 + +236 +237 + +238 + +20 + +239 + +1.0 + +240 +241 + +242 + +true + +243 + +false + +244 + +true + +245 +246 + +odom + +247 + +base_link + +248 + +249 + +``` + +Language: unknown +File: generate_launch_description() +``` +joint_state_publisher_gui_node += +launch_ros.actions.Node +( +package += +'joint_state_publisher_gui' +, + +executable += +'joint_state_publisher_gui' +, + +name += +'joint_state_publisher_gui' +, + +condition += +launch.conditions.IfCondition +( +LaunchConfiguration +( +'gui' +)) +) +``` + +Language: unknown +File: generate_launch_description() +``` +DeclareLaunchArgument +( +name += +'gui' +, +default_value += +'True' +, + +description += +'Flag to enable joint_state_publisher_gui' +) +``` + +Language: unknown +File: generate_launch_description() +``` +joint_state_publisher_node += +launch_ros.actions.Node +( +package += +'joint_state_publisher' +, + +executable += +'joint_state_publisher' +, + +name += +'joint_state_publisher' +, + +arguments +=[ +default_model_path +] +, +#Add this line +parameters +=[{ +'robot_description' +: +Command +([ +'xarcro ' +, +default_model_path +])}] +, +#Remove this line +condition += +launch.conditions.UnlessCondition +( +LaunchConfiguration +( +'gui' +)) +# Remove this line +) +``` + +Language: unknown +File: generate_launch_description() +``` +joint_state_publisher_gui + +``` + +Language: unknown +File: display.launch.py +``` +launch.actions.ExecuteProcess +( +cmd +=[ +'gazebo' +, +'--verbose' +, +'-s' +, +'libgazebo_ros_init.so' +, +'-s' +, +'libgazebo_ros_factory.so' +] +, +output += +'screen' +) +, + +``` + +Language: unknown +File: returnlaunch.LaunchDescription([ +``` +spawn_entity += +launch_ros.actions.Node +( +package += +'gazebo_ros' +, + +executable += +'spawn_entity.py' +, + +arguments +=[ +'-entity' +, +'sam_bot' +, +'-topic' +, +'robot_description' +] +, + +output += +'screen' +) +``` + +Language: unknown +File: rviz_node +``` +robot_state_publisher_node, + +spawn_entity, + +rviz_node + +]) +``` + +Language: unknown +File: /demo/odom +``` +colcon +build +. +install/setup.bash +ros2 +launch +sam_bot_description +display.launch.py + +``` + +Language: unknown +File: sam_bot +``` +ros2 +topic +list + +``` + +Language: unknown +File: /demo/odom +``` +ros2 +topic +info +/demo/imu +ros2 +topic +info +/demo/odom + +``` + +Language: unknown +File: /demo/odom +``` +Type: +sensor_msgs/msg/Imu +Publisher +count: +1 + +Subscription +count: +0 +``` + +Language: unknown +File: /demo/odom +``` +Type: +nav_msgs/msg/Odometry +Publisher +count: +1 + +Subscription +count: +0 +``` + +Language: unknown +File: robot_localization +``` +sudo +apt +install +ros--robot-localization + +``` + +Language: unknown +File: ekf.yaml +``` +### ekf config file ### +ekf_filter_node +: +ros__parameters +: +# The frequency, in Hz, at which the filter will output a position estimate. Note that the filter will not begin +# computation until it receives at least one message from one of theinputs. It will then run continuously at the +# frequency specified here, regardless of whether it receives more measurements. Defaults to 30 if unspecified. +frequency +: +30.0 +# ekf_localization_node and ukf_localization_node both use a 3D omnidirectional motion model. If this parameter is +# set to true, no 3D information will be used in your state estimate. Use this if you are operating in a planar +# environment and want to ignore the effect of small variations in the ground plane that might otherwise be detected +# by, for example, an IMU. Defaults to false if unspecified. +two_d_mode +: +false +# Whether to publish the acceleration state. Defaults to false if unspecified. +publish_acceleration +: +true +# Whether to broadcast the transformation over the /tf topic. Defaultsto true if unspecified. +publish_tf +: +true +# 1. Set the map_frame, odom_frame, and base_link frames to the appropriate frame names for your system. +# 1a. If your system does not have a map_frame, just remove it, and make sure "world_frame" is set to the value of odom_frame. +# 2. If you are fusing continuous position data such as wheel encoder odometry, visual odometry, or IMU data, set "world_frame" +# to your odom_frame value. This is the default behavior for robot_localization's state estimation nodes. +# 3. If you are fusing global absolute position data that is subject to discrete jumps (e.g., GPS or position updates from landmark +# observations) then: +# 3a. Set your "world_frame" to your map_frame value +# 3b. MAKE SURE something else is generating the odom->base_link transform. Note that this can even be another state estimation node +# from robot_localization! However, that instance should *not* fuse the global data. +map_frame +: +map +# Defaults to "map" if unspecified +odom_frame +: +odom +# Defaults to "odom" if unspecified +base_link_frame +: +base_link +# Defaults to "base_link" ifunspecified +world_frame +: +odom +# Defaults to the value ofodom_frame if unspecified +odom0 +: +demo/odom +odom0_config +: +[ +true +, +true +, +true +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +true +, +false +, +false +, +false +] +imu0 +: +demo/imu +imu0_config +: +[ +false +, +false +, +false +, +true +, +true +, +true +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +, +false +] +``` + +Language: unknown +File: returnlaunch.LaunchDescription([ +``` +robot_localization_node += +launch_ros.actions.Node +( +package += +'robot_localization' +, + +executable += +'ekf_node' +, + +name += +'ekf_filter_node' +, + +output += +'screen' +, + +parameters +=[ +os.path.join +( +pkg_share, +'config/ekf.yaml' +) +, +{ +'use_sim_time' +: +LaunchConfiguration +( +'use_sim_time' +)}] +) +``` + +Language: unknown +File: returnlaunch.LaunchDescription([ +``` +launch.actions.DeclareLaunchArgument +( +name += +'use_sim_time' +, +default_value += +'True' +, + +description += +'Flag to enable use_sim_time' +) +, + +``` + +Language: unknown +File: rviz_node +``` +robot_state_publisher_node, + +spawn_entity, + +robot_localization_node, + +rviz_node + +]) +``` + +Language: unknown +File: +``` +robot_localization + +``` + +Language: unknown +File: install(DIRECTORY...) +``` +install +( +DIRECTORY +src +launch +rviz +config + +DESTINATION +share/ +${ +PROJECT_NAME +} +) +``` + +Language: unknown +File: install(DIRECTORY...) +``` +colcon +build +. +install/setup.bash +ros2 +launch +sam_bot_description +display.launch.py + +``` + +Language: unknown +File: /tf +``` +ros2 +topic +list + +``` + +Language: unknown +File: /tf +``` +ros2 +topic +info +/demo/imu +ros2 +topic +info +/demo/odom + +``` + +Language: unknown +File: ekf_filter_node +``` +ros2 +node +info +/ekf_filter_node + +``` + +Language: unknown +File: ekf_filter_node +``` +/ekf_filter_node +Subscribers: + +/demo/imu: +sensor_msgs/msg/Imu + +/demo/odom: +nav_msgs/msg/Odometry + +/parameter_events: +rcl_interfaces/msg/ParameterEvent + +/set_pose: +geometry_msgs/msg/PoseWithCovarianceStamped +Publishers: + +/accel/filtered: +geometry_msgs/msg/AccelWithCovarianceStamped + +/diagnostics: +diagnostic_msgs/msg/DiagnosticArray + +/odometry/filtered: +nav_msgs/msg/Odometry + +/parameter_events: +rcl_interfaces/msg/ParameterEvent + +/rosout: +rcl_interfaces/msg/Log + +/tf: +tf2_msgs/msg/TFMessage +Service +Servers: + +... + +``` + +Language: unknown +File: base_link +``` +ros2 +run +tf2_ros +tf2_echo +odom +base_link + +``` + +Language: unknown +File: base_link +``` +At +time +8 +.842000000 +- +Translation: +[ +0 +.003, +-0.000, +0 +.127 +] + +- +Rotation: +in +Quaternion +[ +-0.000, +0 +.092, +0 +.003, +0 +.996 +] + +At +time +9 +.842000000 +- +Translation: +[ +0 +.002, +-0.000, +0 +.127 +] + +- +Rotation: +in +Quaternion +[ +-0.000, +0 +.092, +0 +.003, +0 +.996 +] +``` diff --git "a/exported_docs/nav2/Setting Up Sensors\357\203\201.txt" "b/exported_docs/nav2/Setting Up Sensors\357\203\201.txt" new file mode 100644 index 0000000..c1ef586 --- /dev/null +++ "b/exported_docs/nav2/Setting Up Sensors\357\203\201.txt" @@ -0,0 +1,1100 @@ +Title: Setting Up Sensors +URL: https://docs.nav2.org/setup_guides/sensors/setup_sensors.html#sensor-introduction +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Sensor Introduction +Mobile robots are equipped with a multitude of sensors that allow them to see and perceive their environment. These sensors obtain information which can be used to build and maintain the map of the environment, to localize the robot on the map, and to see the obstacles in the environment. These tasks are essential to be able to safely and efficiently navigate a robot through a dynamic environment. +Examples of commonly used sensors are lidar, radar, RGB camera, depth camera, IMU, and GPS. To standardize the message formats of these sensors and allow for easier interoperation between vendors, ROS provides thesensor_msgspackage that defines the common sensor interfaces. This also allows users to use any sensor vendor as long as it follows the standard format insensor_msgs. In the next subsection, we introduce some of commonly used messages in navigation, namely thesensor_msgs/LaserScan,sensor_msgs/PointCloud2,sensor_msgs/Range, andsensor_msgs/Image. +Aside from thesensor_msgspackage, there are also theradar_msgsandvision_msgsstandard interfaces you should be aware of. Theradar_msgsdefines the messages for radar-specific sensors while thevision_msgspackage defines the messages used in computer vision such as object detection, segmentation, and other machine learning models. Messages supported by this package arevision_msgs/Classification2D,vision_msgs/Classification3D,vision_msgs/Detection2D, andvision_msgs/Detection3D, to name a few. +Your physical robot’s sensors probably have ROS drivers written for them (e.g. a ROS node that connects to the sensors, populates data into messages, and publishes them for your robot to use) that follow the standard interface in thesensor_msgspackage. Thesensor_msgspackage makes it easy for you to use many different sensors from different manufacturers. General software packages like Nav2 can then read these standardized messages and perform tasks independent of the sensor hardware. On simulated robots such assam_bot, Gazebo has sensor plugins which also publish their information following thesensor_msgspackage. + +## Common Sensor Messages +In this subsection, we discuss some of the common types ofsensor_msgsyou might encounter when setting up Nav2. We will provide a brief description for each sensor, an image of it being simulated in Gazebo and the corresponding visualization of the sensor readings in RViz. + +## sensor_msgs/LaserScan +This message represents a single scan from a planar laser range-finder. This message is used inslam_toolboxandnav2_amclfor localization and mapping, or innav2_costmap_2dfor perception. + +## sensor_msgs/PointCloud2 +This message holds a collection of 3D points, plus optional additional information about each point. This can be from a 3D lidar, a 2D lidar, a depth camera or more. + +## sensor_msgs/Range +This is a single range reading from an active ranger that emits energy and reports one range reading that is valid along an arc at the distance measured. A sonar, IR sensor, or 1D range finder are examples of sensors that use this message. + +## sensor_msgs/Image +This represents the sensor readings from RGB or depth camera, corresponding to RGB or range values. + +## Simulating Sensors using Gazebo +To give you a better grasp of how to set up sensors on a simulated robot, we will build up on our previous tutorials and attach sensors to our simulated robotsam_bot. Similar to the previous tutorial where we used Gazebo plugins to add odometry sensors tosam_bot, we will be using the Gazebo plugins to simulate a lidar sensor and a depth camera onsam_bot. If you are working with a real robot, most of these steps are still required for setting up your URDF frames and it will not hurt to also add in the gazebo plugins for later use. +To be able to follow the rest of this section, make sure that you have properly installed Gazebo. You can follow the instructions at theSetup and Prerequisitesof the previous tutorial to setup Gazebo. + +## Adding Gazebo Plugins to a URDF +Let us first add a lidar sensor tosam_bot. Open the URDF file,src/description/sam_bot_description.urdfand paste the following lines before thetag. +In the code snippet above, we create alidar_linkwhich will be referenced by thegazebo_ros_ray_sensorplugin as the location to attach our sensor. We also set values to the simulated lidar’s scan and range properties. Lastly, we set the/scanas the topic to which it will publish thesensor_msgs/LaserScanmessages. +Next, let us add a depth camera tosam_bot. Paste the following lines after thetag of the lidar sensor. +Similar to the lidar sensor, we createcamera_linkwhich will be referenced by thegazebo_ros_cameraplugin as the sensor attachment location. We also create acamera_depth_framethat is attached to thecamera_linkand will be set as theof the depth camera plugin. We also configure the plugin such that it will publishsensor_msgs/Imageandsensor_msgs/PointCloud2messages to/depth_camera/image_rawand/depth_camera/pointstopics respectively. Lastly, we also set up other basic configuration properties for our depth camera. + +## Launch and Build Files +To verify that the sensors are set up properly and that they can see objects in our environment, let us launchsam_botin a Gazebo world with objects. +Let us create a Gazebo world with a single cube and a single sphere that are within the range ofsam_bot’s sensors so we can verify if it can see the objects correctly. +To create the world, create a directory namedworldat the root of your project and create a file namedmy_world.sdfinside theworldfolder . Then copy the contents ofworld/my_world.sdfand paste them insidemy_world.sdf. +Now, let us edit our launch file,launch/display.launch.py, to launch Gazebo with the world we just created. First, add the path ofmy_world.sdfby adding the following lines inside thegenerate_launch_description(): +Lastly, add the world path in thelaunch.actions.ExecuteProcess(cmd=['gazebo',...line, as shown below. +We also have to add theworlddirectory to ourCMakeLists.txtfile. OpenCmakeLists.txtand append theworlddirectory inside the install(DIRECTORY…), as shown in the snippet below. + +## Build, Run and Verification +We can now build and run our project. Navigate to the root of the project and execute the following lines: +RViz and the Gazebo will then be launched withsam_botpresent in both. In the Gazebo window, the world that we created should be launched andsam_botshould be spawned in that world. You should now be able to observesam_botwith the 360 lidar sensor and the depth camera, as shown in the image below. +In the RViz window, we can verify if we have properly modeled our sensors and if the transforms of our newly added sensors are correct: +Lastly, we can also visualize the sensor readings in RViz. To visualize thesensor_msgs/LaserScanmessage published on/scantopic, click the add button at the bottom part of the RViz window. Then go to theBytopictab and select theLaserScanoption under/scan, as shown below. +Next, set theReliabilityPolicyin RViz toBestEffortand set thesizeto 0.1 to see the points clearer. You should see the visualizedLaserScandetection as shown below. This corresponds to the detected cube and sphere that we added to the Gazebo world. +To visualizesensor_msgs/Imageandsensor_msgs/PointCloud2, do the same for topics/depth_camera/image_rawand/depth_camera/pointsrespectively: +After adding the/depth_camera/image_rawtopic in RViz, set theReliabilityPolicyin RViz toBestEffort. Then you should see the cube in the image window at the lower-left side of the RViz window, as shown below. +You should also see thesensor_msgs/PointCloud2, as shown below. + +## Mapping and Localization +Now that we have a robot with its sensors set up, we can use the obtained sensor information to build a map of the environment and to localize the robot on the map. Theslam_toolboxpackage is a set of tools and capabilities for 2D Simultaneous Localization and Mapping (SLAM) in potentially massive maps with ROS2. It is also one of the officially supported SLAM libraries in Nav2, and we recommend to use this package in situations you need to use SLAM on your robot setup. Aside from theslam_toolbox, localization can also be implemented through thenav2_amclpackage. This package implements Adaptive Monte Carlo Localization (AMCL) which estimates the position and orientation of the robot in a map. Other techniques may also be available, please check Nav2 documentation for more information. +Both theslam_toolboxandnav2_amcluse information from the laser scan sensor to be able to perceive the robot’s environment. Hence, to verify that they can access the laser scan sensor readings, we must make sure that they are subscribed to the correct topic that publishes thesensor_msgs/LaserScanmessage. This can be configured by setting theirscan_topicparameters to the topic that publishes that message. It is a convention to publish thesensor_msgs/LaserScanmessages to/scantopic. Thus, by default, thescan_topicparameter is set to/scan. Recall that when we added the lidar sensor tosam_botin the previous section, we set the topic to which the lidar sensor will publish thesensor_msgs/LaserScanmessages as/scan. +In-depth discussions on the complete configuration parameters will not be a scope of our tutorials since they can be pretty complex. Instead, we recommend you to have a look at their official documentation in the links below. +You can also refer to the(SLAM) Navigating While Mapping guidefor the tutorial on how to use Nav2 with SLAM. You can verify thatslam_toolboxandnav2_amclhave been correctly setup by visualizing the map and the robot’s pose in RViz, similar to what was shown in the previous section. + +## Costmap 2D +The costmap 2D package makes use of the sensor information to provide a representation of the robot’s environment in the form of an occupancy grid. The cells in the occupancy grid store cost values between 0-254 which denote a cost to travel through these zones. A cost of 0 means the cell is free while a cost of 254 means that the cell is lethally occupied. Values in between these extremes are used by navigation algorithms to steer your robot away from obstacles as a potential field. Costmaps in Nav2 are implemented through thenav2_costmap_2dpackage. +The costmap implementation consists of multiple layers, each of which has a certain function that contributes to a cell’s overall cost. The package consists of the following layers, but are plugin-based to allow customization and new layers to be used as well: static layer, inflation layer, range layer, obstacle layer, and voxel layer. The static layer represents the map section of the costmap, obtained from the messages published to the/maptopic like those produced by SLAM. The obstacle layer includes the objects detected by sensors that publish either or both theLaserScanandPointCloud2messages. The voxel layer is similar to the obstacle layer such that it can use either or both theLaserScanandPointCloud2sensor information but handles 3D data instead. The range layer allows for the inclusion of information provided by sonar and infrared sensors. Lastly, the inflation layer represents the added cost values around lethal obstacles such that our robot avoids navigating into obstacles due to the robot’s geometry. In the next subsection of this tutorial, we will have some discussion about the basic configuration of the different layers innav2_costmap_2d. +The layers are integrated into the costmap through a plugin interface and then inflated using a user-specifiedinflation radius, if the inflation layer is enabled. For a deeper discussion on costmap concepts, you can have a look at theROS1 costmap_2D documentation. Note that thenav2_costmap_2dpackage is mostly a straightforward ROS2 port of the ROS1 navigation stack version with minor changes required for ROS2 support and some new layer plugins. + +## Configuring nav2_costmap_2d +In this subsection, we will show an example configuration ofnav2_costmap_2dsuch that it uses the information provided by the lidar sensor ofsam_bot. We will show an example configuration that uses static layer, obstacle layer, voxel layer, and inflation layer. We set both the obstacle and voxel layer to use theLaserScanmessages published to the/scantopic by the lidar sensor. We also set some of the basic parameters to define how the detected obstacles are reflected in the costmap. Note that this configuration is to be included in the configuration file of Nav2. +In the configuration above, notice that we set the parameters for two different costmaps:global_costmapandlocal_costmap. We set up two costmaps since theglobal_costmapis mainly used for long-term planning over the whole map whilelocal_costmapis for short-term planning and collision avoidance. +The layers that we use for our configuration are defined in thepluginsparameter, as shown in line 13 for theglobal_costmapand line 50 for thelocal_costmap. These values are set as a list of mapped layer names that also serve as namespaces for the layer parameters we set up starting at lines 14 and line 51. Note that each layer/namespace in this list must have apluginparameter (as indicated in lines 15, 18, 32, 52, and 68) defining the type of plugin to be loaded for that specific layer. +For the static layer (lines 14-16), we set themap_subscribe_transient_localparameter toTrue. This sets the QoS settings for the map topic. Another important parameter for the static layer is themap_topicwhich defines the map topic to subscribe to. This defaults to/maptopic when not defined. +For the obstacle layer (lines 17-30), we define its sensor source under theobservation_sourcesparameter (line 20) asscanwhose parameters are set up in lines 22-30. We set itstopicparameter as the topic that publishes the defined sensor source and we set thedata_typeaccording to the sensor source it will use. In our configuration, the obstacle layer will use theLaserScanpublished by the lidar sensor to/scan. +Note that the obstacle layer and voxel layer can use either or bothLaserScanandPointCloud2as theirdata_typebut it is set toLaserScanby default. The code snippet below shows an example of using both theLaserScanandPointCloud2as the sensor sources. This may be particularly useful when setting up your own physical robot. +For the other parameters of the obstacle layer, themax_obstacle_heightparameter sets the maximum height of the sensor reading to return to the occupancy grid. The minimum height of the sensor reading can also be set using themin_obstacle_heightparameter, which defaults to 0 since we did not set it in the configuration. Theclearingparameter is used to set whether the obstacle is to be removed from the costmap or not. The clearing operation is done by raytracing through the grid. The maximum and minimum range to raytrace clear objects from the costmap is set using theraytrace_max_rangeandraytrace_min_rangerespectively. Themarkingparameter is used to set whether the inserted obstacle is marked into the costmap or not. We also set the maximum and minimum range to mark obstacles in the costmap through theobstacle_max_rangeandobstacle_min_rangerespectively. +For the inflation layer (lines 31-34 and 67-70), we set the exponential decay factor across the inflation radius using thecost_scaling_factorparameter. The value of the radius to inflate around lethal obstacles is defined using theinflation_radius. +For the voxel layer (lines 51-66), we set thepublish_voxel_mapparameter toTrueto enable the publishing of the 3D voxel grid. The resolution of the voxels in height is defined using thez_resolutionparameter, while the number of voxels in each column is defined using thez_voxelsparameter. Themark_thresholdparameter sets the minimum number of voxels in a column to mark as occupied in the occupancy grid. We set theobservation_sourcesparameter of the voxel layer toscan, and we set the scan parameters (in lines 61-66) similar to the parameters that we have discussed for the obstacle layer. As defined in itstopicanddata_typeparameters, the voxel layer will use theLaserScanpublished on the/scantopic by the lidar scanner. +Note that the we are not using a range layer for our configuration but it may be useful for your own robot setup. For the range layer, its basic parameters are thetopics,input_sensor_type, andclear_on_max_readingparameters. The range topics to subscribe to are defined in thetopicsparameter. Theinput_sensor_typeis set to eitherALL,VARIABLE, orFIXED. Theclear_on_max_readingis a boolean parameter that sets whether to clear the sensor readings on max range. Have a look at the configuration guide in the link below in case you need to set it up. + +## Build, Run and Verification +We will first launchdisplay.launch.pywhich launches the robot state publisher that provides thebase_link=>sensorstransformations in our URDF. It also launches Gazebo that acts as our physics simulator and also provides theodom=>base_linkfrom the differential drive plugin, which we added tosam_botin the previous guide,Simulating an Odometry System Using Gazebo. It also launches RViz which we can use to visualize the robot and sensor information. +Then we will launchslam_toolboxto publish to/maptopic and provide themap=>odomtransform. Recall that themap=>odomtransform is one of the primary requirements of the Nav2 system. The messages published on the/maptopic will then be used by the static layer of theglobal_costmap. +After we have properly setup our robot description, odometry sensors, and necessary transforms, we will finally launch the Nav2 system itself. For now, we will only be exploring the costmap generation system of Nav2. After launching Nav2, we will visualize the costmaps in RViz to confirm our output. + +## Launching Description Nodes, RViz and Gazebo +Let us now launch our Robot Description Nodes, RViz and Gazebo through the launch filedisplay.launch.py. Open a new terminal and execute the lines below. +RViz and the Gazebo should now be launched withsam_botpresent in both. Recall that thebase_link=>sensorstransform is now being published byrobot_state_publisherand theodom=>base_linktransform by our Gazebo plugins. Both transforms should now be displayed show without errors in RViz. + +## Launching slam_toolbox +To be able to launchslam_toolbox, make sure that you have installed theslam_toolboxpackage by executing the following command: +We will launch theasync_slam_toolbox_nodeofslam_toolboxusing the package’s built-in launch files. Open a new terminal and then execute the following lines: +Theslam_toolboxshould now be publishing to the/maptopic and providing themap=>odomtransform. +We can verify in RViz that the/maptopic is being published. In the RViz window, click the add button at the bottom-left part then go toBytopictab then select theMapunder the/maptopic. You should be able to visualize the message received in the/mapas shown in the image below. +We can also check that the transforms are correct by executing the following lines in a new terminal: +Note: For Galactic and newer, it should beview_framesand notview_frames.pyThe line above will create aframes.pdffile that shows the current transform tree. Your transform tree should be similar to the one shown below: + +## Launching Nav2 +First, Make sure you have installed the Nav2 packages by executing the following: +We will now launch Nav2 using thenav2_bringup’s built-in launch file,navigation_launch.py. Open a new terminal and execute the following: +Note that the parameters of thenav2_costmap_2dthat we discussed in the previous subsection are included in the default parameters ofnavigation_launch.py. Aside from thenav2_costmap_2dparameters, it also contains parameters for the other nodes that are included in Nav2 implementation. +After we have properly set up and launched Nav2, the/global_costmapand/local_costmaptopics should now be active. + +## Visualizing Costmaps in RViz +Theglobal_costmap,local_costmapand the voxel representation of the detected obstacles can be visualized in RViz. +To visualize theglobal_costmapin RViz, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select theMapunder the/global_costmap/costmaptopic. Theglobal_costmapshould show in the RViz window, as shown below. Theglobal_costmapshows areas which should be avoided (black) by our robot when it navigates our simulated world in Gazebo. +To visualize thelocal_costmapin RViz, select theMapunder the/local_costmap/costmaptopic. Set thecolorschemein RViz tocostmapto make it appear similar to the image below. +To visualize the voxel representation of the detected object, open a new terminal and execute the following lines: +The line above sets the topic where the the markers will be published to/my_marker. To see the markers in RViz, selectMarkerunder the/my_markertopic, as shown below. +Then set thefixedframein RViz toodomand you should now see the voxels in RViz, which represent the cube and the sphere that we have in the Gazebo world: + +## Conclusion +In this section of our robot setup guide, we have discussed the importance of sensor information for different tasks associated with Nav2. More specifically, tasks such as mapping (SLAM), localization (AMCL), and perception (costmap) tasks. +We also had a discussion on the common types of sensor messages in Nav2 which standardize the message formats for different sensor vendors. We also discussed how to add sensors to a simulated robot using Gazebo and how to verify that the sensors are working correctly through RViz. +Lastly, we set up a basic configuration for thenav2_costmap_2dpackage using different layers to produce a global and local costmap. We then verify our work by visualizing these costmaps in RViz. + +Code Examples: + +Language: unknown +File: +``` +251 + +252 + +253 + +254 + +255 + +256 + +257 +258 + +259 + +260 + +261 + +262 + +263 + +264 +265 + +266 + +267 + +268 + +269 + +270 + +271 + +272 +273 + +274 + +275 + +276 + +277 + +278 +279 + +280 + +281 + +true + +282 + +true + +283 + +5 + +284 + +285 + +286 + +287 + +360 + +288 + +1.000000 + +289 + +0.000000 + +290 + +6.280000 + +291 + +292 + +293 + +294 + +0.120000 + +295 + +3.5 + +296 + +0.015000 + +297 + +298 + +299 + +gaussian + +300 + +0.0 + +301 + +0.01 + +302 + +303 + +304 + +305 + +306 + +~/out:=scan + +307 + +308 + +sensor_msgs/LaserScan + +309 + +lidar_link + +310 + +311 + +312 + +``` + +Language: unknown +File: +``` +314 + +315 + +316 + +317 + +318 + +319 + +320 + +321 +322 + +323 + +324 + +325 + +326 + +327 + +328 +329 + +330 + +331 + +332 + +333 + +334 + +335 +336 + +337 + +338 + +339 + +340 + +341 +342 + +343 +344 + +345 + +346 + +347 + +348 + +349 +350 + +351 + +352 + +true + +353 + +30.0 + +354 + +355 + +1.047198 + +356 + +357 + +640 + +358 + +480 + +359 + +R8G8B8 + +360 + +361 + +362 + +0.05 + +363 + +3 + +364 + +365 + +366 + +367 + +0.2 + +368 + +true + +369 + +0.0 + +370 + +camera_depth_frame + +371 + +0.5 + +372 + +3.0 + +373 + +0 + +374 + +0 + +375 + +0 + +376 + +0 + +377 + +0 + +378 + +0 + +379 + +0 + +380 + +0 + +381 + +0 + +382 + +0 + +383 + +384 + +385 + +``` + +Language: unknown +File: generate_launch_description() +``` +world_path += +os.path.join +( +pkg_share, +'world/my_world.sdf' +) +``` + +Language: unknown +File: launch.actions.ExecuteProcess(cmd=['gazebo',... +``` +launch.actions.ExecuteProcess +( +cmd +=[ +'gazebo' +, +'--verbose' +, +'-s' +, +'libgazebo_ros_init.so' +, +'-s' +, +'libgazebo_ros_factory.so' +, +world_path +] +, +output += +'screen' +) +, + +``` + +Language: unknown +File: world +``` +install +( +DIRECTORY +src +launch +rviz +config +world + +DESTINATION +share/ +${ +PROJECT_NAME +} +) +``` + +Language: unknown +File: world +``` +colcon +build +. +install/setup.bash +ros2 +launch +sam_bot_description +display.launch.py + +``` + +Language: unknown +File: /scan +``` + 1 +global_costmap +: + 2 +global_costmap +: + 3 +ros__parameters +: + 4 +update_frequency +: +1.0 + 5 +publish_frequency +: +1.0 + 6 +global_frame +: +map + 7 +robot_base_frame +: +base_link + 8 +use_sim_time +: +True + 9 +robot_radius +: +0.22 +10 +resolution +: +0.05 +11 +track_unknown_space +: +false +12 +rolling_window +: +false +13 +plugins +: +[ +"static_layer" +, +"obstacle_layer" +, +"inflation_layer" +] +14 +static_layer +: +15 +plugin +: +"nav2_costmap_2d::StaticLayer" +16 +map_subscribe_transient_local +: +True +17 +obstacle_layer +: +18 +plugin +: +"nav2_costmap_2d::ObstacleLayer" +19 +enabled +: +True +20 +observation_sources +: +scan +21 +scan +: +22 +topic +: +/scan +23 +max_obstacle_height +: +2.0 +24 +clearing +: +True +25 +marking +: +True +26 +data_type +: +"LaserScan" +27 +raytrace_max_range +: +3.0 +28 +raytrace_min_range +: +0.0 +29 +obstacle_max_range +: +2.5 +30 +obstacle_min_range +: +0.0 +31 +inflation_layer +: +32 +plugin +: +"nav2_costmap_2d::InflationLayer" +33 +cost_scaling_factor +: +3.0 +34 +inflation_radius +: +0.55 +35 +always_send_full_costmap +: +True +36 +37 +local_costmap +: +38 +local_costmap +: +39 +ros__parameters +: +40 +update_frequency +: +5.0 +41 +publish_frequency +: +2.0 +42 +global_frame +: +odom +43 +robot_base_frame +: +base_link +44 +use_sim_time +: +True +45 +rolling_window +: +true +46 +width +: +3 +47 +height +: +3 +48 +resolution +: +0.05 +49 +robot_radius +: +0.22 +50 +plugins +: +[ +"voxel_layer" +, +"inflation_layer" +] +51 +voxel_layer +: +52 +plugin +: +"nav2_costmap_2d::VoxelLayer" +53 +enabled +: +True +54 +publish_voxel_map +: +True +55 +origin_z +: +0.0 +56 +z_resolution +: +0.05 +57 +z_voxels +: +16 +58 +max_obstacle_height +: +2.0 +59 +mark_threshold +: +0 +60 +observation_sources +: +scan +61 +scan +: +62 +topic +: +/scan +63 +max_obstacle_height +: +2.0 +64 +clearing +: +True +65 +marking +: +True +66 +data_type +: +"LaserScan" +67 +inflation_layer +: +68 +plugin +: +"nav2_costmap_2d::InflationLayer" +69 +cost_scaling_factor +: +3.0 +70 +inflation_radius +: +0.55 +71 +always_send_full_costmap +: +True +``` + +Language: unknown +File: PointCloud2 +``` +obstacle_layer: + +plugin: +"nav2_costmap_2d::ObstacleLayer" +enabled: +True + +observation_sources: +scan +pointcloud + +scan: + +topic: +/scan + +data_type: +"LaserScan" +pointcloud: + +topic: +/depth_camera/points + +data_type: +"PointCloud2" +``` + +Language: unknown +File: display.launch.py +``` +colcon +build +. +install/setup.bash +ros2 +launch +sam_bot_description +display.launch.py + +``` + +Language: unknown +File: slam_toolbox +``` +sudo +apt +install +ros--slam-toolbox + +``` + +Language: unknown +File: slam_toolbox +``` +ros2 +launch +slam_toolbox +online_async_launch.py + +``` + +Language: unknown +File: /map +``` +ros2 +run +tf2_tools +view_frames.py + +``` + +Language: unknown +File: frames.pdf +``` +sudo +apt +install +ros--navigation2 +sudo +apt +install +ros--nav2-bringup + +``` + +Language: unknown +File: navigation_launch.py +``` +ros2 +launch +nav2_bringup +navigation_launch.py + +``` + +Language: unknown +File: costmap +``` +ros2 +run +nav2_costmap_2d +nav2_costmap_2d_markers +voxel_grid: += +/local_costmap/voxel_grid +visualization_marker: += +/my_marker + +``` diff --git "a/exported_docs/nav2/Setting Up The URDF\357\203\201.txt" "b/exported_docs/nav2/Setting Up The URDF\357\203\201.txt" new file mode 100644 index 0000000..7bb01b0 --- /dev/null +++ "b/exported_docs/nav2/Setting Up The URDF\357\203\201.txt" @@ -0,0 +1,1215 @@ +Title: Setting Up The URDF +URL: https://docs.nav2.org/setup_guides/urdf/setup_urdf.html#urdf-and-the-robot-state-publisher +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## URDF and the Robot State Publisher +As discussed in the previous tutorial, one of the requirements for Navigation2 is the transformation frombase_linkto the various sensors and reference frames. This transformation tree can range from a simple tree with only one link from thebase_linktolaser_linkor a tree comprised of multiple sensors located in different locations, each having their own coordinate frame. Creating multiple publishers to handle all of these coordinate frame transformations may become tedious. Therefore, we will be making use of the Robot State Publisher package to publish our transforms. +The Robot State Publisher is a package of ROS 2 that interacts with the tf2 package to publish all of the necessary transforms that can be directly inferred from the geometry and structure of the robot. We need to provide it with the correct URDF and it will automatically handle publishing the transforms. This is very useful for complex transformations but it is still recommended for simpler transform trees. +The Unified Robot Description Format (URDF) is an XML file that represents a robot model. In this tutorial, it will mainly be used to build transformations trees related with the robot geometry, but it also has other uses. One example is how it can be used in visualizing your robot model in RVIZ, a 3D Visualization tool for ROS, by defining visual components such as materials and meshes. Another example is how the URDF can be used to define the physical properties of the robot. These properties are then used in physics simulators such as Gazebo to simulate how your robot will interact in an environment. +Another major feature of URDF is that it also supports Xacro (XML Macros) to help you create a shorter and readable XML to help in defining complex robots. We can use these macros to eliminate the need for repeating blocks of XML in our URDF. Xacro is also useful in defining configuration constants which can be reused throughout the URDF. + +## Setting Up the Environment +In this guide, we are assuming that you are already familiar with ROS 2 and how to setup your development environment, so we’ll breeze through the steps in this section. +Let’s begin by installing some additional ROS 2 packages that we will be using during this tutorial. +Next, create a directory for your project, initialize a ROS 2 workspace and give your robot a name. For ours, we’ll be calling itsam_bot. + +## Writing the URDF +Now that we have our project workspace set up, let’s dive straight into writing the URDF. Below is an image of the robot we will be trying to build. +Next, let us define some constants using XAcro properties that will be reused throughout the URDF. +Here is a brief discussion on what these properties will represent in our urdf. Thebase_*properties all define the size of the robot’s main chassis. Thewheel_radiusandwheel_widthdefine the shape of the robot’s two back wheels. Thewheel_ygapadjusts the gap between the wheel and the chassis along the y-axis whilstwheel_zoffandwheel_xoffposition the back wheels along the z-axis and x-axis appropriately. Lastly, thecaster_xoffpositions the front caster wheel along the x-axis. +Let us then define ourbase_link- this link will be a large box and will act as the main chassis of our robot. In URDF, alinkelement describes a rigid part or component of our robot. The robot state publisher then utilizes these definitions to determine coordinate frames for each link and publish the transformations between them. +We will also be defining some of the link’s visual properties which can be used by tools such as Gazebo and Rviz to show us a 3D model of our robot. Amongst these properties arewhich describes the link’s shape andwhich describes it’s color. +For the code block block below, we access thebaseproperties from the robot constants sections we defined before using the${property}syntax. In addition, we also set the material color of the main chassis toCyan. Note that we set these parameters under thetag so they will only be applied as visual parameters which dont affect any collision or physical properties. +Next, let us define abase_footprintlink. Thebase_footprintlink is a virtual (non-physical) link which has no dimensions or collision areas. Its primary purpose is to enable various packages determine the center of a robot projected to the ground. For example, Navigation2 uses this link to determine the center of a circular footprint used in its obstacle avoidance algorithms. Again, we set this link with no dimensions and to which position the robot’s center is in when it is projected to the ground plane. +After defining our base_link, we then add a joint to connect it tobase_link. In URDF, ajointelement describes the kinematic and dynamic properties between coordinate frames. For this case, we will be defining afixedjoint with the appropriate offsets to place ourbase_footprintlink in the proper location based on the description above. Remember that we want to set our base_footprint to be at the ground plane when projected from the center of the main chassis, hence we get the sum of thewheel_radiusand thewheel_zoffto get the appropriate location along the z-axis. +Now, we will be adding two large drive wheels to our robot. To make our code cleaner and avoid repetition, we will make use of macros to define a block of code that will be repeated with differing parameters. Our macro will have 3 params:prefixwhich simply adds a prefix to our link and joint names, andx_reflectandy_reflectwhich allows us to flip the positions of our wheels with respect to the x and y axis respectively. Within this macro, we can also define the visual properties of a single wheel. Lastly, we will also define acontinuousjoint to allow our wheels to freely rotate about an axis. This joint also connects our wheel to thebase_linkat the appropriate location. +At the end of this code block, we will be instantiating two wheels using the macro we just made through thexacro:wheeltags. Note that we also define the parameters to have one wheel on both sides at the back of our robot. +Next, we will be adding a caster wheel at the front of our robot. We will be modelling this wheel as a sphere to keep things simple. Again, we define the wheel’s geometry, material and the joint to connect it tobase_linkat the appropriate location. +And that’s it! We have built a URDF for a simple differential drive robot. In the next section, we will focus on building the ROS Package containing our URDF, launching the robot state publisher, and visualizing the robot in RVIz. + +## Build and Launch +Let’s start this section by adding some dependencies that will be required once we build this project. Open up the root of your project directory and add the following lines to yourpackage.xml(preferably after thetag) +Next, let us create our launch file. Launch files are used by ROS 2 to bring up the necessary nodes for our package. From the root of the project, create a directory namedlaunchand adisplay.launch.pyfile within it. The launch file below launches a robot publisher node in ROS 2 that uses our URDF to publish the transforms for our robot. In addition, the launch file also automatically launches RVIZ so we can visualize our robot as defined by the URDF. Copy and paste the snippet below into yourdisplay.launch.pyfile. +To keep things simpler when we get to visualization, we have provided an RVIz config file that will be loaded when we launch our package. This configuration file initializes RVIz with the proper settings so you can view the robot immediately once it launches. Create a directory namedrvizin the root of your project and a file namedurdf_config.rvizunder it. Place the following as the contents ofurdf_config.rviz +Lastly, let us modify theCMakeLists.txtfile in the project root directory to include the files we just created during the package installation process. Add the following snippet toCMakeLists.txtfile preferably above theif(BUILD_TESTING)line: +We are now ready to build our project using colcon. Navigate to the project root and execute the following commands. +After a successful build, execute the following commands to install the ROS 2 package and launch our project. +ROS 2 should now launch a robot publisher node and start up RVIZ using our URDF. We’ll be taking a look at our robot using RVIZ in the next section. + +## Visualization using RVIZ +RVIZ is a robot visualization tool that allows us to see a 3D model of our robot using its URDF. Upon a successful launch using the commands in the previous section, RVIZ should now be visible on your screen and should look like the image below. You may need to move around and manipulate the view to get a good look at your robot. +As you can see, we have successfully created a simple differential drive robot and visualized it in RVIz. It is not necessary to visualize your robot in RVIz, but it’s a good step in order to see if you have properly defined your URDF. This helps you ensure that the robot state publisher is publishing the correct transformations. +You may have noticed that another window was launched - this is a GUI for the joint state publisher. The joint state publisher is another ROS 2 package which publishes the state for our non-fixed joints. You can manipulate this publisher through the small GUI and the new pose of the joints will be reflected in RVIz. Sliding the bars for any of the two wheels will rotate these joints. You can see this in action by viewing RVIZ as you sweep the sliders in the Joint State Publisher GUI. +At this point, you may already decide to stop with this tutorial since we have already achieved our objective of creating a URDF for a simple differential drive robot. The robot state publisher is now publishing the transforms derived from the URDF. These transforms can now be used by other packages (such as Nav2) to get information regarding the shape and structure of your robot. However, to properly use this URDF in a simulation, we need physical properties so that the robot reacts to physical environments like a real robot would. The visualization fields are only for visualization, not collision, so your robot will drive straight through obstacles. We’ll get into adding these properties in our URDF in the next section. + +## Adding Physical Properties +As an additional section to this guide, we will be modifying our current URDF to include some of our robot’s kinematic properties. This information may be used by physics simulators such as Gazebo to model and simulate how our robot will act in the virtual environment. +Let us first define macros containing the inertial properties of the geometric primitives we used in our project. Place the snippet below after our constants section in the URDF: +Let us start by adding collision areas to ourbase_linkusing thetag. We will also be using the box_inertia macro we defined before to add some inertial properties to ourbase_link. Include the following code snippet withintag of base_link in our URDF. +Next, let us do the same for our wheel macros. Include the following code snippet within thetag of our wheel macros in our URDF. +Lastly, let us add the similar properties to our spherical caster wheels. Include the following in thetag of our caster wheel in the URDF. +Build your project and then launch RViz using the same commands in the previous section. +You can verify whether you have properly set up the collision areas by enablingCollisionEnabledunderRobotModelon the left pane (it may be easier to see if you also turn offVisualEnabled). For this tutorial we defined a collision area which is similar to our visual properties. Note that this may not always be the case since you may opt for simpler collision areas based on how your robot looks. +For now, we will have to stop here since we will need to set up a lot more components to actually start simulating our robot in Gazebo. We will be coming back to this project during the course of these setup guides, and we will eventually see our robot move in a virtual environment once we get to the simulation sections. The major components that are missing from this work are the simulation plugins required to mimic your robot controllers. We will introduce those and add them to this URDF in the appropriate section. + +## Conclusion +And that’s it. In this tutorial, you have successfully created a URDF for a simple differential drive robot. You have also set up a ROS 2 project that launches a robot publisher node, which then uses your URDF to publish the robot’s transforms. We have also used RViz to visualize our robot to verify whether our URDF is correct. Lastly, we have added in some physical properties to our URDF in order to prepare it for simulation. +Feel free to use this tutorial as a template for your own robot. Remember that your main goal is to publish the correct transforms from your base_link up to your sensor_frames. Once these have been setup, then you may proceed to our other setup guides. + +Code Examples: + +Language: unknown +File: laser_link +``` +sudo +apt +install +ros--joint-state-publisher-gui +sudo +apt +install +ros--xacro + +``` + +Language: unknown +File: sam_bot +``` +ros2 +pkg +create +--build-type +ament_cmake +sam_bot_description + +``` + +Language: unknown +File: src/description +``` +1 + +2 + +3 +4 +5 +6 + +``` + +Language: unknown +File: +``` + 4 + + 5 + + 6 + + 7 + + 8 + 9 + +10 + +11 + +12 + +13 + +14 +15 + +``` + +Language: unknown +File: +``` +17 + +18 + +19 + +20 + +21 + +22 + +23 + +24 + +25 + +26 + +27 + +``` + +Language: unknown +File: wheel_zoff +``` +29 + +30 + +31 +32 + +33 + +34 + +35 + +36 + +``` + +Language: unknown +File: xacro:wheel +``` +38 + +39 + +40 + +41 + +42 + +43 + +44 + +45 + +46 + +47 + +48 + +49 + +50 + +51 +52 + +53 + +54 + +55 + +56 + +57 + +58 + +59 +60 + +61 + +``` + +Language: unknown +File: base_link +``` +63 + +64 + +65 + +66 + +67 + +68 + +69 + +70 + +71 + +72 + +73 + +74 +75 + +76 + +77 + +78 + +79 + +``` + +Language: unknown +File: +``` + +joint_state_publisher + + +joint_state_publisher_gui + + +robot_state_publisher + + +rviz + + +xacro + +``` + +Language: unknown +File: display.launch.py +``` +import +launch +from +launch.substitutions +import +Command +, +LaunchConfiguration +import +launch_ros +import +os +def +generate_launch_description +(): +pkg_share += +launch_ros +. +substitutions +. +FindPackageShare +( +package += +'sam_bot_description' +) +. +find +( +'sam_bot_description' +) +default_model_path += +os +. +path +. +join +( +pkg_share +, +'src/description/sam_bot_description.urdf' +) +default_rviz_config_path += +os +. +path +. +join +( +pkg_share +, +'rviz/urdf_config.rviz' +) +robot_state_publisher_node += +launch_ros +. +actions +. +Node +( +package += +'robot_state_publisher' +, +executable += +'robot_state_publisher' +, +parameters += +[{ +'robot_description' +: +Command +([ +'xacro ' +, +LaunchConfiguration +( +'model' +)])}] +) +joint_state_publisher_node += +launch_ros +. +actions +. +Node +( +package += +'joint_state_publisher' +, +executable += +'joint_state_publisher' +, +name += +'joint_state_publisher' +, +parameters += +[{ +'robot_description' +: +Command +([ +'xacro ' +, +default_model_path +])}], +condition += +launch +. +conditions +. +UnlessCondition +( +LaunchConfiguration +( +'gui' +)) +) +joint_state_publisher_gui_node += +launch_ros +. +actions +. +Node +( +package += +'joint_state_publisher_gui' +, +executable += +'joint_state_publisher_gui' +, +name += +'joint_state_publisher_gui' +, +condition += +launch +. +conditions +. +IfCondition +( +LaunchConfiguration +( +'gui' +)) +) +rviz_node += +launch_ros +. +actions +. +Node +( +package += +'rviz2' +, +executable += +'rviz2' +, +name += +'rviz2' +, +output += +'screen' +, +arguments += +[ +'-d' +, +LaunchConfiguration +( +'rvizconfig' +)], +) +return +launch +. +LaunchDescription +([ +launch +. +actions +. +DeclareLaunchArgument +( +name += +'gui' +, +default_value += +'True' +, +description += +'Flag to enable joint_state_publisher_gui' +), +launch +. +actions +. +DeclareLaunchArgument +( +name += +'model' +, +default_value += +default_model_path +, +description += +'Absolute path to robot urdf file' +), +launch +. +actions +. +DeclareLaunchArgument +( +name += +'rvizconfig' +, +default_value += +default_rviz_config_path +, +description += +'Absolute path to rviz config file' +), +joint_state_publisher_node +, +joint_state_publisher_gui_node +, +robot_state_publisher_node +, +rviz_node +]) +``` + +Language: unknown +File: urdf_config.rviz +``` +Panels: + +- +Class: +rviz_common/Displays + +Help +Height: +78 +Name: +Displays + +Property +Tree +Widget: + +Expanded: + +- +/Global +Options1 + +- +/Status1 + +- +/RobotModel1/Links1 + +- +/TF1 + +Splitter +Ratio: +0 +.5 + +Tree +Height: +557 + +Visualization +Manager: + +Class: +"" +Displays: + +- +Alpha: +0 +.5 + +Cell +Size: +1 +Class: +rviz_default_plugins/Grid + +Color: +160 +; +160 +; +164 +Enabled: +true +Name: +Grid + +- +Alpha: +0 +.6 + +Class: +rviz_default_plugins/RobotModel + +Description +Topic: + +Depth: +5 +Durability +Policy: +Volatile + +History +Policy: +Keep +Last + +Reliability +Policy: +Reliable + +Value: +/robot_description + +Enabled: +true +Name: +RobotModel + +Visual +Enabled: +true +- +Class: +rviz_default_plugins/TF + +Enabled: +true +Name: +TF + +Marker +Scale: +0 +.3 + +Show +Arrows: +true +Show +Axes: +true +Show +Names: +true +Enabled: +true +Global +Options: + +Background +Color: +48 +; +48 +; +48 +Fixed +Frame: +base_link + +Frame +Rate: +30 +Name: +root + +Tools: + +- +Class: +rviz_default_plugins/Interact + +Hide +Inactive +Objects: +true +- +Class: +rviz_default_plugins/MoveCamera + +- +Class: +rviz_default_plugins/Select + +- +Class: +rviz_default_plugins/FocusCamera + +- +Class: +rviz_default_plugins/Measure + +Line +color: +128 +; +128 +; +0 +Transformation: + +Current: + +Class: +rviz_default_plugins/TF + +Value: +true +Views: + +Current: + +Class: +rviz_default_plugins/Orbit + +Name: +Current +View + +Target +Frame: + + +Value: +Orbit +( +rviz +) +Saved: +~ + +``` + +Language: unknown +File: if(BUILD_TESTING) +``` +install +( +DIRECTORY +src +launch +rviz + +DESTINATION +share/ +${ +PROJECT_NAME +} +) +``` + +Language: unknown +File: if(BUILD_TESTING) +``` +colcon +build +. +install/setup.bash + +``` + +Language: unknown +File: if(BUILD_TESTING) +``` +ros2 +launch +sam_bot_description +display.launch.py + +``` + +Language: unknown +File: if(BUILD_TESTING) +``` +17 + +18 + +19 + +20 + +21 + +22 + +23 + +24 + +25 +26 + +27 + +28 + +29 + +30 + +31 + +32 + +33 +34 + +35 + +36 + +37 + +38 + +39 + +``` + +Language: unknown +File: +``` +52 + +53 + +54 + +55 + +56 + +57 +58 + +``` + +Language: unknown +File: +``` +83 + +84 + +85 + +86 + +87 + +88 + +89 +90 + +``` + +Language: unknown +File: +``` +114 + +115 + +116 + +117 + +118 + +119 + +120 +121 + +``` + +Language: unknown +File: base_footprint +``` +colcon +build +. +install/setup.bash +ros2 +launch +sam_bot_description +display.launch.py + +``` diff --git "a/exported_docs/nav2/Setting Up Transformations\357\203\201.txt" "b/exported_docs/nav2/Setting Up Transformations\357\203\201.txt" new file mode 100644 index 0000000..0ef7684 --- /dev/null +++ "b/exported_docs/nav2/Setting Up Transformations\357\203\201.txt" @@ -0,0 +1,106 @@ +Title: Setting Up Transformations +URL: https://docs.nav2.org/setup_guides/transformation/setup_transforms.html#transforms-in-navigation2 +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Transforms Introduction +Many ROS packages require the transform tree of a robot to be published using the TF2 ROS package. A transformation tree defines the relations between different coordinate systems, in terms of translation, rotation, and relative motion. To make this more concrete, let us apply an example of a simple robot that has a mobile base with a single laser sensor mounted on top of it. +This robot has two defined coordinate frames: one corresponding to the center point of the mobile base of the robot, and one for the center point of the laser that is mounted on top of the base. We’ll call the coordinate frame attached to the mobile basebase_linkand we’ll call the coordinate frame attached to the laserbase_laser. Note that will be talking more about the naming and conventions of these coordinate frames in the next section. +At this point, let’s assume that we have some data from the laser in the form of distance measurements from the laser’s center point. In other words, we have some data in thebase_lasercoordinate frame. +Now, suppose we want to take this data and use it to help the mobile base avoid obstacles in the world. To do this successfully, we need a way to transform the laser scan we’ve received from thebase_laserframe to thebase_linkframe. In essence, we need to define a relationship between thebase_laserandbase_linkcoordinate frames. +In defining this relationship, let us assume that the only data we have is that the laser is mounted 10cm forward and 20cm above the center point of the mobile base. This gives us a translational offset that relates thebase_linkframe to thebase_laserframe. Specifically, we know that to get data from thebase_linkframe to thebase_laserframe, we must apply a translation of (x: 0.1m, y: 0.0m, z: 0.2m), and transversely, to get data from thebase_laserframe to thebase_linkframe, we must apply the opposite translation (x: -0.1m, y: 0.0m, z: -0.20m). +We could choose to manage this relationship ourselves, meaning to store and apply the appropriate translations between the frames when necessary, but this becomes a real pain as the number of coordinate frames increases. Luckily, we don’t have to do this work ourselves. Instead, we’ll define the relationship betweenbase_linkandbase_laseronce using TF2 and let it manage the transformation between the two coordinate frames for us. This is especially useful when working with non-static transformations, such as a set of frames that are moving relative to each other, like a robot base frame in a map frame. +To define and store the relationship between thebase_linkandbase_laserframes using TF2, we need to add them to a transform tree. Conceptually, each node in the transform tree corresponds to a coordinate frame, and each edge corresponds to the transform that needs to be applied to move from the current node to its child. TF2 uses a tree structure to guarantee that there is only a single traversal that links any two coordinate frames together, and assumes that all edges in the tree are directed from parent to child nodes. +To create a transform tree for our simple example, we’ll create two nodes: one for thebase_linkcoordinate frame and one for thebase_lasercoordinate frame. To create the edge between them, we first need to decide which node will be the parent and which will be the child. Remember — this distinction is important because TF2 assumes that all transforms move from parent to child. +Let’s choose thebase_linkcoordinate frame as the parent because when other pieces/sensors are added to the robot, it will make the most sense for them to relate to thebase_laserframe by traversing through thebase_linkframe. This means that the transform associated with the edge connectingbase_linkandbase_lasershould be (x: 0.1m, y: 0.0m, z: 0.2m). +With this transform tree set up, converting the laser scan received in thebase_laserframe to thebase_linkframe is as simple as making a call to the TF2 library. Our robot can now use this information to reason about laser scans in thebase_linkframe and safely plan around obstacles in its environment. + +## Static Transform Publisher Demo +Now let’s try publishing a very simple transform using the static_transform_publisher tool provided by TF2. We will be publishing a transformation from the linkbase_linkto the linkbase_laserwith a translation of (x: 0.1m, y: 0.0m, z: 0.2m). Note that we will be building the transform from the diagram earlier in this tutorial. +Open up your command line and execute the following command: +With this, we are now successfully publishing ourbase_linktobase_lasertransform in TF2. Let us now check if it is working properly throughtf2_echo. Open up a separate command line window and execute the following: +You should be able to observe a repeated output similar to the one below. +And that’s it for this short demo - we were able to successfully publish a transform frombase_linktobase_laserusing the TF2 library. Note that we do not recommend using the above demo in publishing transforms for your actual robotics projects, it is just a quick demo to see TF2 in action. For a real robot system, we would create a URDF file which embeds this information and more about your robot for use of the robot_state_publisher rather than the static_transform_publisher. There are more suitable and practical ways to go about this which will be discussed in theSetting Up The URDFtutorial. + +## Transforms in Navigation2 +There are two important ROS REPs which we highly suggest for you to check out. These documents detail some standards set about by the ROS community to ensure proper operation across different packages. Nav2 also adheres to these standards and conventions. +To quickly summarize REP 105, this document specifies the naming conventions and semantic meanings of the different coordinate frames used in ROS. Of interest to this tutorial are thebase_link,odomandmapcoordinate frames. Thebase_linkis a coordinate frame that is attached to a fixed position on the robot, typically at its main chassis and its rotational center. Theodomcoordinate frame is a fixed frame relative to the robot’s starting position and is mainly used for locally-consistent representations of distances. Lastly, themapcoordinate frame is a world fixed frame that is used for globally-consistent representations of distances. +REP 103, on the other hand, discusses some standard units of measure and other related conventions to keep integration issues between different ROS packages to a minimum. The basic overview is that frames are defined using the right hand rule, with Z up and X forward, and units should be standard SI units. +Now let’s move on to some specifics for the Navigation2 package to function correctly. Nav2 requires the following transformations to be published in ROS: +The first transformmap=>odomis usually provided by a different ROS package dealing with localization and mapping such as AMCL. This transform updates live in use so we don’t set static values for this in our robot’s TF tree. Further detail about how to set this up may be pretty complex, so we highly suggest to have a look at the documentation of the mapping or localization package you are using for your platform. All ROS compliant SLAM and localization packages will provide you with this transformation automatically on launch. +Theodom=>base_linkis usually published by our odometry system using sensors such as wheel encoders. This is typically computed via sensor fusion of odometry sensors (IMU, wheel encoders, VIO, etc) using therobot_localizationpackage. +All other statically defined transforms (e.g.base_link=>base_laser,base_link=>wheels,wheels=>IMU, etc) is what we will be talking about for the rest of this guide. This transformation tree is used by Nav2 to properly relate the information from sensors or other frame of interest to the rest of the robot. The transformation between these two coordinate frames is usually provided to Nav2 through the Robot State Publisher and the Universal Robot Descriptor File (URDF). In cases where there are more sensor coordinate frames on your platform, then a transform tree frombase_linkto each sensor coordinate frame needs to be published. + +## Conclusion +In this tutorial, we have discussed about the concept of transforms and how they are used in Nav2. +In the last section, we have also explored using the static_transform_publisher of TF2 to publish our transforms. You may use this to set up your transforms for Nav2, but this is generally not the best way to do it. In most robotics projects, we make use of the Robot State Publisher since it is much easier to use and scales well as our robot gets more complex. We will be talking about the Robot State Publisher, URDF, and how to set it up in the next tutorial onSetting Up The URDF. +Lastly, we also discussed the three published transform requirements of Nav2 and the necessary REPs to keep in mind when setting them up. + +Code Examples: + +Language: unknown +File: base_laser +``` +ros2 +run +tf2_ros +static_transform_publisher +0 +.1 +0 +0 +.2 +0 +0 +0 +base_link +base_laser + +``` + +Language: unknown +File: tf2_echo +``` +ros2 +run +tf2_ros +tf2_echo +base_link +base_laser + +``` + +Language: unknown +File: tf2_echo +``` +At +time +0 +.0 +- +Translation: +[ +0 +.100, +0 +.000, +0 +.200 +] + +- +Rotation: +in +Quaternion +[ +0 +.000, +0 +.000, +0 +.000, +1 +.000 +] +``` diff --git "a/exported_docs/nav2/Setting Up the Robot\342\200\231s Footprint\357\203\201.txt" "b/exported_docs/nav2/Setting Up the Robot\342\200\231s Footprint\357\203\201.txt" new file mode 100644 index 0000000..e85d8ae --- /dev/null +++ "b/exported_docs/nav2/Setting Up the Robot\342\200\231s Footprint\357\203\201.txt" @@ -0,0 +1,131 @@ +Title: Setting Up the Robot’s Footprint +URL: https://docs.nav2.org/setup_guides/footprint/setup_footprint.html#configuring-the-robot-s-footprint +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Footprint Introduction +The footprint outlines the robot’s 2D shape when projected to the ground and is primarily used by Nav2 to avoid collisions during planning. The algorithms involved in this task makes sure that the robot does not collide with the obstacles in the costmap while it computes the robot’s paths or plans. +The footprint is set up using thefootprintorrobot_radiusparameter of the global and local costmaps which we tackled in the previous tutorials (Setting Up Sensors Guide). The value defined in thefootprintparameter is an ordered vector of 2-D points defining the robot’s footprint with thebase_linkframe as the origin. The first and last points in the vector are joined into the last line segment to close the footprint’s shape. As an alternative, you may also use therobot_radiusparameter wherein circular footprint is automatically generated and centered atbase_link. In cases both thefootprintandrobot_radiusparameters have been defined in the configuration, thefootprintis used. +For the global costmap footprint, the decision to choose between therobot_radius(circular) orfootprint(polygon) parameter depends on the robot, its environment, and the path planning algorithm you will use. Even if you are working with a non-circular robot, there may be situations where a circular footprint is acceptable. For example, path planning algorithms likeNavFnassume that the robot is circular since it only checks for collision per grid cell, so it will not be necessary to outline the robot’s exact shape for its footprint. On the other hand, algorithms such asSmac Planner’s Hybrid-A*perform collision checking on the robot’s polygon-shaped footprint if possible and necessary. Hence, it might be useful to use a polygon-shaped footprint. Another example is having a small RC car sized robot roaming a warehouse. This robot is so small it won’t need to make confined maneuvers – thusly approximating it with the largest cross-sectional radius is a good time-saving optimization. +For the local costmap footprint, it is typical for non-circular robots to be set up withfootprint(polygon). Some situations where this is not recommended is when you do not have enough computing resources to implement collision avoidance algorithms on a polygon-shaped footprint. Another possible reason to userobot_radius(circular) for the local costmap is when the robot is very small relative to its environment such that precise collision avoidance is not necessary. However, generally the local trajectory planner should use the actual footprint polygon of the robot. +Note that this can also be adjusted over time using the costmap’s~/footprinttopic, which will update the polygon over time as needed due to changes in the robot’s state, such as movement of an attached manipulator, picking up a pallet, or other actions that adjust a robot’s shape. That polygon will then automatically be used by the planners and controllers. + +## Configuring the Robot’s Footprint +In this section, we will configure the footprint ofsam_botsuch thatfootprint(polygon) is used for the local costmap androbot_radius(circular) is used for the global costmap. We will utilize the default configuration file of Nav2 with a modified footprint parameter for the global and local costmaps. +Under theconfigdirectory, create a new file namednav2_params.yaml. Next, copy the contents ofconfig/nav2_params.yamland paste them into the newly created file. The contents ofconfig/nav2_params.yamlare copied from the default configuration file of Nav2 but with changes in thefootprintandrobot_radiusparameters to match the shape ofsam_bot. +Below is the code snippet fromnav2_params.yamldefining the local costmap footprint. In this configuration file, thefootprintparameter of the local costmap has already been set with a rectangular-shaped footprint. This box is centered at thebase_linkframe ofsam_bot. +For the global costmap, we have already set therobot_radiusparameter to create a circular footprint that matchessam_bot’s size and centered atbase_link. The parameter that was modified is shown in the code snippet below. + +## Build, Run and Verification +We will now confirm that we have properly set upsam_bot’s footprint. +First, we launchlaunch/display.launch.pyto launch the robot state publisher, spawnsam_botin Gazebo, and visualizesam_botand its footprint in Rviz. The robot state publisher publishes thebase_link=>sensorstransforms defined insam_bot’s URDF, while Gazebo’s differential drive plugin publishes theodom=>base_linktransform. Open a new terminal and execute the lines below. +After launchingdisplay.launch.py, RViz and Gazebo should open. RViz should showsam_bot, the frames ofsam_bot’s parts, and theodomframe without errors. Gazebo should showsam_botwith a sphere and a cube detectable bysambot’s lidar sensor. +Next, we will publish themap=>odomtransform using thestatic_transform_publisher. We publish themap=>odomtransform as static in this guide as a simple way to publish the transform and visualize the footprint. Open a new terminal and execute the lines below. +Themap=>odomtransform should now be being published and themapframe should be added in RViz without errors. +Lastly, we will launch Nav2 using thenav2_params.yamlconfiguration file we just made andnavigation_launch.py, the built-in launch file ofnav2_bringup. Open a new terminal and execute the following: +We should now be able to visualize the footprints in RViz, which will be discussed in the next section. + +## Visualizing Footprint in RViz +To visualize the footprint of the local costmap, click the add button at the bottom-left part of the RViz window. Under theBytopictab, select thePolygonunder the/local_costmap/published_footprinttopic, as shown below. +Set the fixed frame in RViz toodomand you should see the rectangular-shaped footprint ofsam_bot: +On the other hand, for the global costmap, click the add button at the bottom-left part of the RViz window. Go toBytopictab then select thePolygonunder the/global_costmap/published_footprinttopic, as shown below. +Set the fixed frame in RViz tomapand you should see the circular footprint ofsam_bot: + +## Conclusion +In this guide, we have shown how to configure a circular and polygon-shaped footprint for your robot. This footprint is important since it plays a major role in Nav2’s pathfinding algorithms function. +As a demo, we have configured the costmap footprint parameters ofsam_bot. We set the local costmap to use a polygon-shaped footprint followingsam_bot’s shape while we set the the global costmap to use a circular footprint. Lastly, we visualized and confirmed the footprints of the local and global costmaps in RViz. + +Code Examples: + +Language: unknown +File: sam_bot +``` +188 +resolution +: +0.05 +189 +footprint +: +"[ +[0.21, +0.195], +[0.21, +-0.195], +[-0.21, +-0.195], +[-0.21, +0.195] +]" +190 +plugins +: +[ +"voxel_layer" +, +"inflation_layer" +] +``` + +Language: unknown +File: base_link +``` +232 +use_sim_time +: +True +233 +robot_radius +: +0.3 +234 +resolution +: +0.05 +``` + +Language: unknown +File: base_link +``` +colcon +build +. +install/setup.bash +ros2 +launch +sam_bot_description +display.launch.py + +``` + +Language: unknown +File: odom +``` +ros2 +run +tf2_ros +static_transform_publisher +0 +0 +0 +0 +0 +0 +map +odom + +``` + +Language: unknown +File: nav2_bringup +``` +ros2 +launch +nav2_bringup +navigation_launch.py +params_file: += + + +``` diff --git "a/exported_docs/nav2/Simple Commander API\357\203\201.txt" "b/exported_docs/nav2/Simple Commander API\357\203\201.txt" new file mode 100644 index 0000000..84ac230 --- /dev/null +++ "b/exported_docs/nav2/Simple Commander API\357\203\201.txt" @@ -0,0 +1,150 @@ +Title: Simple Commander API +URL: https://docs.nav2.org/commander_api/index.html +Section: commander_api/index.html +-------------------------------------------------------------------------------- + + +## Overview +The goal of the Nav2 Simple (Python3) Commander is to provide a “navigation as a library” capability to Python3 users. We provide an API that handles all the ROS 2 and Action Server tasks for you such that you can focus on building an application leveraging the capabilities of Nav2 (after you’ve configured it to your liking with your plugins of choice).We also provide you with demos and examples of API usageto build common basic capabilities in autonomous mobile robotics in thenav2_simple_commanderpackage. +A simple demonstration is shown below. Note:goToPose(),goThroughPoses(),followWaypoints()and similar arenon-blockingsuch that you can receive and process feedback in a single-threaded application. As such while waiting for a task to be completed, thewhilenotnav.isTaskComplete()design is necessary to poll for changes in the navigation completion, and if not complete some tasks of interest to your application (like processing feedback, doing something with the data the robot is collecting, or checking for faults). +You may use this simple commander preempt commands of the same type (e.g. you can preempt agoToPose()with anothergoToPose()) but you must explicitly cancel a current command and issue a new one if switching betweengoToPose(),goThroughPoses(), orfollowWaypoints(). + +## Commander API +The methods provided by the basic navigator are shown below, with inputs and expected returns. +If a server fails, it may throw an exception or return aNoneobject, so please be sure to properly wrap your navigation calls in try/catch and check returns forNonetype. +New as of September 2023: the simple navigator constructor will accept anamespacefield to support multi-robot applications or namespaced Nav2 launches. + +## Costmap API +This is a Python3 API for costmap 2d messages from the stack. It provides the basic conversion, get/set, and handling semantics found in the costmap 2d C++ API. + +## Footprint Collision Checker API +This is a Python3 API for a Footprint Collision Checker. +It provides the needed methods to manipulate the coordinates +and calculate the cost of a Footprint in a given map. + +## Examples and Demos +All of these can be found in thepackage. +Thenav2_simple_commanderhas a few examples to highlight the API functions available to you as a user: +Thenav2_simple_commanderhas a few demonstrations to highlight a couple of simple autonomy applications you can build using the API: + +Code Examples: + +Language: unknown +File: followWaypoints() +``` +from +nav2_simple_commander.robot_navigator +import +BasicNavigator +import +rclpy +rclpy +. +init +() +nav += +BasicNavigator +() +# ... +nav +. +setInitialPose +( +init_pose +) +nav +. +waitUntilNav2Active +() +# if autostarted, else use lifecycleStartup() +# ... +path += +nav +. +getPath +( +init_pose +, +goal_pose +) +smoothed_path += +nav +. +smoothPath +( +path +) +# ... +nav +. +goToPose +( +goal_pose +) +while +not +nav +. +isTaskComplete +(): +feedback += +nav +. +getFeedback +() +if +feedback +. +navigation_duration +> +600 +: +nav +. +cancelTask +() +# ... +result += +nav +. +getResult +() +if +result +== +TaskResult +. +SUCCEEDED +: +print +( +'Goal succeeded!' +) +elif +result +== +TaskResult +. +CANCELED +: +print +( +'Goal was canceled!' +) +elif +result +== +TaskResult +. +FAILED +: +print +( +'Goal failed!' +) +``` diff --git "a/exported_docs/nav2/Simple Smoother\357\203\201.txt" "b/exported_docs/nav2/Simple Smoother\357\203\201.txt" new file mode 100644 index 0000000..e1dca63 --- /dev/null +++ "b/exported_docs/nav2/Simple Smoother\357\203\201.txt" @@ -0,0 +1,62 @@ +Title: Simple Smoother +URL: https://docs.nav2.org/configuration/packages/configuring-simple-smoother.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Simple Smoother Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: >=1 +``` +smoother_server +: +ros__parameters +: +costmap_topic +: +global_costmap/costmap_raw +footprint_topic +: +global_costmap/published_footprint +robot_base_frame +: +base_link +transform_timeout +: +0.1 +smoother_plugins +: +[ +"simple_smoother" +] +simple_smoother +: +plugin +: +"nav2_smoother::SimpleSmoother" +tolerance +: +1.0e-10 +do_refinement +: +True +refinement_num +: +2 +max_its +: +1000 +w_data +: +0.2 +w_smooth +: +0.3 +``` diff --git "a/exported_docs/nav2/SimpleGoalChecker\357\203\201.txt" "b/exported_docs/nav2/SimpleGoalChecker\357\203\201.txt" new file mode 100644 index 0000000..e7cb750 --- /dev/null +++ "b/exported_docs/nav2/SimpleGoalChecker\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: SimpleGoalChecker +URL: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/simple_goal_checker.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_controller plugin name defined in thegoal_checker_plugin_idparameter inController Server. diff --git "a/exported_docs/nav2/SimpleProgressChecker\357\203\201.txt" "b/exported_docs/nav2/SimpleProgressChecker\357\203\201.txt" new file mode 100644 index 0000000..02b7e30 --- /dev/null +++ "b/exported_docs/nav2/SimpleProgressChecker\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: SimpleProgressChecker +URL: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/simple_progress_checker.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_controller plugin name defined in theprogress_checker_plugin_idparameter inController Server. diff --git "a/exported_docs/nav2/SingleTrigger\357\203\201.txt" "b/exported_docs/nav2/SingleTrigger\357\203\201.txt" new file mode 100644 index 0000000..cf0d2de --- /dev/null +++ "b/exported_docs/nav2/SingleTrigger\357\203\201.txt" @@ -0,0 +1,18 @@ +Title: SingleTrigger +URL: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/SingleTrigger.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + + + +``` diff --git "a/exported_docs/nav2/Smac 2D Planner\357\203\201.txt" "b/exported_docs/nav2/Smac 2D Planner\357\203\201.txt" new file mode 100644 index 0000000..5df794d --- /dev/null +++ "b/exported_docs/nav2/Smac 2D Planner\357\203\201.txt" @@ -0,0 +1,86 @@ +Title: Smac 2D Planner +URL: https://docs.nav2.org/configuration/packages/smac/configuring-smac-2d.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: +``` +planner_server +: +ros__parameters +: +planner_plugins +: +[ +"GridBased" +] +use_sim_time +: +True +GridBased +: +plugin +: +"nav2_smac_planner::SmacPlanner2D" +# In Iron and older versions, "/" was used instead of "::" +tolerance +: +0.125 +# tolerance for planning if unable to reach exact pose, in meters +downsample_costmap +: +false +# whether or not to downsample the map +downsampling_factor +: +1 +# multiplier for the resolution of the costmap layer (e.g. 2 on a 5cm costmap would be 10cm) +allow_unknown +: +true +# allow traveling in unknown space +max_iterations +: +1000000 +# maximum total iterations to search for before failing (in case unreachable), set to -1 to disable +max_on_approach_iterations +: +1000 +# maximum number of iterations to attempt to reach goal once in tolerance +max_planning_time +: +2.0 +# max time in s for planner to plan, smooth +cost_travel_multiplier +: +2.0 +# Cost multiplier to apply to search to steer away from high cost areas. Larger values will place in the center of aisles more exactly (if non-`FREE` cost potential field exists) but take slightly longer to compute. To optimize for speed, a value of 1.0 is reasonable. A reasonable tradeoff value is 2.0. A value of 0.0 effective disables steering away from obstacles and acts like a naive binary search A*. +use_final_approach_orientation +: +false +# Whether to set the final path pose at the goal's orientation to the requested orientation (false) or in line with the approach angle so the robot doesn't rotate to heading (true) +smoother +: +max_iterations +: +1000 +w_smooth +: +0.3 +w_data +: +0.2 +tolerance +: +1.0e-10 +``` diff --git "a/exported_docs/nav2/Smac Hybrid-A* Planner\357\203\201.txt" "b/exported_docs/nav2/Smac Hybrid-A* Planner\357\203\201.txt" new file mode 100644 index 0000000..fec0f67 --- /dev/null +++ "b/exported_docs/nav2/Smac Hybrid-A* Planner\357\203\201.txt" @@ -0,0 +1,156 @@ +Title: Smac Hybrid-A* Planner +URL: https://docs.nav2.org/configuration/packages/smac/configuring-smac-hybrid.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: >=1 +``` +planner_server +: +ros__parameters +: +planner_plugins +: +[ +"GridBased" +] +use_sim_time +: +True +GridBased +: +plugin +: +"nav2_smac_planner::SmacPlannerHybrid" +# In Iron and older versions, "/" was used instead of "::" +downsample_costmap +: +false +# whether or not to downsample the map +downsampling_factor +: +1 +# multiplier for the resolution of the costmap layer (e.g. 2 on a 5cm costmap would be 10cm) +tolerance +: +0.25 +# dist-to-goal heuristic cost (distance) for valid tolerance endpoints if exact goal cannot be found. +allow_unknown +: +true +# allow traveling in unknown space +max_iterations +: +1000000 +# maximum total iterations to search for before failing (in case unreachable), set to -1 to disable +max_on_approach_iterations +: +1000 +# Maximum number of iterations after within tolerances to continue to try to find exact solution +max_planning_time +: +5.0 +# max time in s for planner to plan, smooth +motion_model_for_search +: +"DUBIN" +# Hybrid-A* Dubin, Redds-Shepp +angle_quantization_bins +: +72 +# Number of angle bins for search +analytic_expansion_ratio +: +3.5 +# The ratio to attempt analytic expansions during search for final approach. +analytic_expansion_max_length +: +3.0 +# For Hybrid/Lattice nodes: The maximum length of the analytic expansion to be considered valid to prevent unsafe shortcutting +analytic_expansion_max_cost +: +200.0 +# The maximum single cost for any part of an analytic expansion to contain and be valid, except when necessary on approach to goal +analytic_expansion_max_cost_override +: +false +# Whether or not to override the maximum cost setting if within critical distance to goal (ie probably required) +minimum_turning_radius +: +0.40 +# minimum turning radius in m of path / vehicle +reverse_penalty +: +2.0 +# Penalty to apply if motion is reversing, must be => 1 +change_penalty +: +0.0 +# Penalty to apply if motion is changing directions (L to R), must be >= 0 +non_straight_penalty +: +1.2 +# Penalty to apply if motion is non-straight, must be => 1 +cost_penalty +: +2.0 +# Penalty to apply to higher cost areas when adding into the obstacle map dynamic programming distance expansion heuristic. This drives the robot more towards the center of passages. A value between 1.3 - 3.5 is reasonable. +retrospective_penalty +: +0.015 +lookup_table_size +: +20.0 +# Size of the dubin/reeds-sheep distance window to cache, in meters. +cache_obstacle_heuristic +: +false +# Cache the obstacle map dynamic programming distance expansion heuristic between subsequent replannings of the same goal location. Dramatically speeds up replanning performance (40x) if costmap is largely static. +debug_visualizations +: +false +# For Hybrid nodes: Whether to publish expansions on the /expansions topic as an array of poses (the orientation has no meaning) and the path's footprints on the /planned_footprints topic. WARNING: heavy to compute and to display, for debug only as it degrades the performance. +use_quadratic_cost_penalty +: +False +downsample_obstacle_heuristic +: +True +allow_primitive_interpolation +: +False +smooth_path +: +True +# If true, does a simple and quick smoothing post-processing to the path +smoother +: +max_iterations +: +1000 +w_smooth +: +0.3 +w_data +: +0.2 +tolerance +: +1.0e-10 +do_refinement +: +true +refinement_num +: +2 +``` diff --git "a/exported_docs/nav2/Smac Planner\357\203\201.txt" "b/exported_docs/nav2/Smac Planner\357\203\201.txt" new file mode 100644 index 0000000..099654e --- /dev/null +++ "b/exported_docs/nav2/Smac Planner\357\203\201.txt" @@ -0,0 +1,14 @@ +Title: Smac Planner +URL: https://docs.nav2.org/configuration/packages/configuring-smac-planner.html#provided-plugins +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Provided Plugins + + +## Description +Thenav2_smac_plannerpackage contains an optimized templated A* search algorithm used to create multiple A*-based planners for multiple types of robot platforms. It uses template node types to develop different search-based planners. +We support circular differential-drive and omni-directional drive robots using theSmacPlanner2Dplanner which implements a cost-aware A* planner. We support car-like (ackermann) and legged vehicles using theSmacPlannerHybridplugin which implements a Hybrid-A* planner. We support non-circular, arbitrary shaped, any model vehicles using theSmacPlannerLatticeplugin which implements a State Lattice planner (e.g. omni, diff, ackermann, legged, custom). It contains control sets and generators for ackermann, legged, differential drive and omnidirectional vehicles, but you may provide your own for another robot type or to have different planning behaviors. +The last two plugins are bothkinematically feasibleand supportreversing. They have performance similar to its 2D counter parts like 2D-A* and NavFn via highly optimized heuristic functions and efficient programming. An example of the 3 planners can be seen below, planning a roughly 75 m path. +Usual planning times are below 100ms for some environments, occasionally approaching up to 200ms. The performance of all 3 planners is roughly comparable with naive 2D search algorithms that have long been mainstays of the ROS Navigation ecosystem, but also achieving kinematic feasibility, support for reversing, and using modern state of the art techniques. diff --git "a/exported_docs/nav2/Smac State Lattice Planner\357\203\201.txt" "b/exported_docs/nav2/Smac State Lattice Planner\357\203\201.txt" new file mode 100644 index 0000000..f2c23eb --- /dev/null +++ "b/exported_docs/nav2/Smac State Lattice Planner\357\203\201.txt" @@ -0,0 +1,135 @@ +Title: Smac State Lattice Planner +URL: https://docs.nav2.org/configuration/packages/smac/configuring-smac-lattice.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: >=1 +``` +planner_server +: +ros__parameters +: +planner_plugins +: +[ +"GridBased" +] +use_sim_time +: +True +GridBased +: +plugin +: +"nav2_smac_planner::SmacPlannerLattice" +# In Iron and older versions, "/" was used instead of "::" +allow_unknown +: +true +# Allow traveling in unknown space +tolerance +: +0.25 +# dist-to-goal heuristic cost (distance) for valid tolerance endpoints if exact goal cannot be found. +max_iterations +: +1000000 +# Maximum total iterations to search for before failing (in case unreachable), set to -1 to disable +max_on_approach_iterations +: +1000 +# Maximum number of iterations after within tolerances to continue to try to find exact solution +max_planning_time +: +5.0 +# Max time in s for planner to plan, smooth +analytic_expansion_ratio +: +3.5 +# The ratio to attempt analytic expansions during search for final approach. +analytic_expansion_max_length +: +3.0 +# For Hybrid/Lattice nodes The maximum length of the analytic expansion to be considered valid to prevent unsafe shortcutting +analytic_expansion_max_cost +: +200.0 +# The maximum single cost for any part of an analytic expansion to contain and be valid, except when necessary on approach to goal +analytic_expansion_max_cost_override +: +false +# Whether or not to override the maximum cost setting if within critical distance to goal (ie probably required) +reverse_penalty +: +2.0 +# Penalty to apply if motion is reversing, must be => 1 +change_penalty +: +0.05 +# Penalty to apply if motion is changing directions (L to R), must be >= 0 +non_straight_penalty +: +1.05 +# Penalty to apply if motion is non-straight, must be => 1 +cost_penalty +: +2.0 +# Penalty to apply to higher cost areas when adding into the obstacle map dynamic programming distance expansion heuristic. This drives the robot more towards the center of passages. A value between 1.3 - 3.5 is reasonable. +rotation_penalty +: +5.0 +# Penalty to apply to in-place rotations, if minimum control set contains them +retrospective_penalty +: +0.015 +lattice_filepath +: +"" +# The filepath to the state lattice graph +lookup_table_size +: +20.0 +# Size of the dubin/reeds-sheep distance window to cache, in meters. +cache_obstacle_heuristic +: +false +# Cache the obstacle map dynamic programming distance expansion heuristic between subsequent replannings of the same goal location. Dramatically speeds up replanning performance (40x) if costmap is largely static. +allow_reverse_expansion +: +false +# If true, allows the robot to use the primitives to expand in the mirrored opposite direction of the current robot's orientation (to reverse). +smooth_path +: +True +# If true, does a simple and quick smoothing post-processing to the path +smoother +: +max_iterations +: +1000 +w_smooth +: +0.3 +w_data +: +0.2 +tolerance +: +1.0e-10 +do_refinement +: +true +refinement_num +: +2 +``` diff --git "a/exported_docs/nav2/SmoothPath\357\203\201.txt" "b/exported_docs/nav2/SmoothPath\357\203\201.txt" new file mode 100644 index 0000000..54433a6 --- /dev/null +++ "b/exported_docs/nav2/SmoothPath\357\203\201.txt" @@ -0,0 +1,39 @@ +Title: SmoothPath +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Smooth.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: SmoothPath +``` + +``` diff --git "a/exported_docs/nav2/Smoother Server\357\203\201.txt" "b/exported_docs/nav2/Smoother Server\357\203\201.txt" new file mode 100644 index 0000000..fd444f4 --- /dev/null +++ "b/exported_docs/nav2/Smoother Server\357\203\201.txt" @@ -0,0 +1,76 @@ +Title: Smoother Server +URL: https://docs.nav2.org/configuration/packages/configuring-smoother-server.html#example +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Smoother Server Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: plugin +``` +smoother_server +: +ros__parameters +: +smoother_plugins +: +[ +"simple_smoother" +, +"curvature_smoother" +] +curvature_smoother +: +plugin +: +"nav2_ceres_costaware_smoother/CeresCostawareSmoother" +simple_smoother +: +plugin +: +"nav2_smoother::SimpleSmoother" +``` + +Language: unknown +File: plugin +``` +smoother_server +: +ros__parameters +: +costmap_topic +: +global_costmap/costmap_raw +footprint_topic +: +global_costmap/published_footprint +robot_base_frame +: +base_link +transform_timeout +: +0.1 +smoother_plugins +: +[ +"simple_smoother" +] +simple_smoother +: +plugin +: +"nav2_smoother::SimpleSmoother" +tolerance +: +1.0e-10 +do_refinement +: +True +``` diff --git "a/exported_docs/nav2/SmootherSelector\357\203\201.txt" "b/exported_docs/nav2/SmootherSelector\357\203\201.txt" new file mode 100644 index 0000000..5555aff --- /dev/null +++ "b/exported_docs/nav2/SmootherSelector\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: SmootherSelector +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/SmootherSelector.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: transientlocal +``` + +``` diff --git "a/exported_docs/nav2/Speed Filter Parameters\357\203\201.txt" "b/exported_docs/nav2/Speed Filter Parameters\357\203\201.txt" new file mode 100644 index 0000000..7b00c7e --- /dev/null +++ "b/exported_docs/nav2/Speed Filter Parameters\357\203\201.txt" @@ -0,0 +1,54 @@ +Title: Speed Filter Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/speed_filter.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: +``` +global_costmap +: +global_costmap +: +ros__parameters +: +... +plugins +: +[ +"static_layer" +, +"obstacle_layer" +, +"inflation_layer" +] +filters +: +[ +"speed_filter" +] +... +speed_filter +: +plugin +: +"nav2_costmap_2d::SpeedFilter" +enabled +: +True +filter_info_topic +: +"/costmap_filter_info" +speed_limit_topic +: +"/speed_limit" +transform_tolerance +: +0.1 +``` diff --git "a/exported_docs/nav2/SpeedController\357\203\201.txt" "b/exported_docs/nav2/SpeedController\357\203\201.txt" new file mode 100644 index 0000000..f1e72b3 --- /dev/null +++ "b/exported_docs/nav2/SpeedController\357\203\201.txt" @@ -0,0 +1,32 @@ +Title: SpeedController +URL: https://docs.nav2.org/configuration/packages/bt-plugins/decorators/SpeedController.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: GoalReached +``` + + + +``` diff --git "a/exported_docs/nav2/Spin\357\203\201.txt" "b/exported_docs/nav2/Spin\357\203\201.txt" new file mode 100644 index 0000000..c7d9a5f --- /dev/null +++ "b/exported_docs/nav2/Spin\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: Spin +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Spin.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: Spin +``` + +``` diff --git "a/exported_docs/nav2/StandardTrajectoryGenerator\357\203\201.txt" "b/exported_docs/nav2/StandardTrajectoryGenerator\357\203\201.txt" new file mode 100644 index 0000000..6594da1 --- /dev/null +++ "b/exported_docs/nav2/StandardTrajectoryGenerator\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: StandardTrajectoryGenerator +URL: https://docs.nav2.org/configuration/packages/dwb-plugins/standard_traj_generator.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. diff --git "a/exported_docs/nav2/Static Layer Parameters\357\203\201.txt" "b/exported_docs/nav2/Static Layer Parameters\357\203\201.txt" new file mode 100644 index 0000000..8144c95 --- /dev/null +++ "b/exported_docs/nav2/Static Layer Parameters\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Static Layer Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/static.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/StoppedGoalChecker\357\203\201.txt" "b/exported_docs/nav2/StoppedGoalChecker\357\203\201.txt" new file mode 100644 index 0000000..ee4f47e --- /dev/null +++ "b/exported_docs/nav2/StoppedGoalChecker\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: StoppedGoalChecker +URL: https://docs.nav2.org/configuration/packages/nav2_controller-plugins/stopped_goal_checker.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_controller plugin name defined in thegoal_checker_plugin_idparameter inController Server. diff --git "a/exported_docs/nav2/Theta Star Planner\357\203\201.txt" "b/exported_docs/nav2/Theta Star Planner\357\203\201.txt" new file mode 100644 index 0000000..1d92823 --- /dev/null +++ "b/exported_docs/nav2/Theta Star Planner\357\203\201.txt" @@ -0,0 +1,51 @@ +Title: Theta Star Planner +URL: https://docs.nav2.org/configuration/packages/configuring-thetastar.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +The parameters of the planner are: + +## Example + + +Code Examples: + +Language: unknown +File: +``` +planner_server +: +ros__parameters +: +expected_planner_frequency +: +20.0 +use_sim_time +: +True +planner_plugins +: +[ +"GridBased" +] +GridBased +: +plugin +: +"nav2_theta_star_planner::ThetaStarPlanner" +# In Iron and older versions, "/" was used instead of "::" +how_many_corners +: +8 +w_euc_cost +: +1.0 +w_traversal_cost +: +2.0 +w_heuristic_cost +: +1.0 +``` diff --git "a/exported_docs/nav2/TimeExpired\357\203\201.txt" "b/exported_docs/nav2/TimeExpired\357\203\201.txt" new file mode 100644 index 0000000..9a90a4d --- /dev/null +++ "b/exported_docs/nav2/TimeExpired\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: TimeExpired +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/TimeExpired.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/TransformAvailable\357\203\201.txt" "b/exported_docs/nav2/TransformAvailable\357\203\201.txt" new file mode 100644 index 0000000..3c5592b --- /dev/null +++ "b/exported_docs/nav2/TransformAvailable\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: TransformAvailable +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/TransformAvailable.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/TruncatePathLocal\357\203\201.txt" "b/exported_docs/nav2/TruncatePathLocal\357\203\201.txt" new file mode 100644 index 0000000..aabd4b6 --- /dev/null +++ "b/exported_docs/nav2/TruncatePathLocal\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: TruncatePathLocal +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/TruncatePathLocal.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/TruncatePath\357\203\201.txt" "b/exported_docs/nav2/TruncatePath\357\203\201.txt" new file mode 100644 index 0000000..ee8df5c --- /dev/null +++ "b/exported_docs/nav2/TruncatePath\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: TruncatePath +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/TruncatePath.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/Tuning Guide\357\203\201.txt" "b/exported_docs/nav2/Tuning Guide\357\203\201.txt" new file mode 100644 index 0000000..c238a8b --- /dev/null +++ "b/exported_docs/nav2/Tuning Guide\357\203\201.txt" @@ -0,0 +1,59 @@ +Title: Tuning Guide +URL: https://docs.nav2.org/tuning/index.html +Section: tuning/index.html +-------------------------------------------------------------------------------- + + +## Inflation Potential Fields +Many users and ecosystem navigation configuration files the maintainers find are really missing the point of the inflation layer. While it’s true that you can simply inflate a small radius around the walls to weight against critical collisions, thetruevalue of the inflation layer is creating a consistent potential field around the entire map. +Some of the most popular tuning guides for ROS Navigation / Nav2 evencall this out specificallythat there’s substantial benefit to creating a gentle potential field across the width of the map - after inscribed costs are applied - yet very few users do this in practice. +This habit actually results in paths produced by NavFn, Theta*, and Smac Planner to be somewhat suboptimal. They really want to look for a smooth potential field rather than wide open 0-cost spaces in order to stay in the middle of spaces and deal with close-by moving obstacles better. It will allow search to be weighted towards freespace far before the search algorithm runs into the obstacle that the inflation is caused by, letting the planner give obstacles as wide of a berth as possible. +So it is the maintainers’ recommendation, as well as all other cost-aware search planners available in ROS, to increase your inflation layer cost scale and radius in order to adequately produce a smooth potential across the entire map. For very large open spaces, its fine to have 0-cost areas in the middle, but for halls, aisles, and similar;please create a smooth potential to provide the best performance. + +## Robot Footprint vs Radius +Nav2 allows users to specify the robot’s shape in 2 ways: a geometricfootprintor the radius of a circle encompassing the robot. In ROS (1), it was pretty reasonable to always specify a radius approximation of the robot, since the global planning algorithms didn’t use it and the local planners / costmaps were set up with the circular assumption baked in. +However, in Nav2, we now have multiple planning and controller algorithms that make use of the full SE2 footprint. If your robot is non-circular, it is recommended that you give the planners and controllers the actual, geometric footprint of your robot. This will allow the planners and controllers to plan or create trajectories into tighter spaces. For example, if you have a very long but skinny robot, the circular assumption wouldn’t allow a robot to plan into a space only a little wider than your robot, since the robot would not fit length-wise. +The kinematically feasible planners (e.g. Smac Hybrid-A*, Smac State Lattice) will use the SE2 footprint for collision checking to create kinematically feasible plans, if provided with the actual footprint. As of December, 2021 all of the controller plugins support full footprint collision checking to ensure safe path tracking. If you provide a footprint of your robot, it will be used to make sure trajectories are valid and it is recommended you do so. It will prevent a number of “stuck robot” situations that could have been easily avoided. +If your robot is truly circular, continue to use therobot_radiusparameter. The three valid reasons for a non-circular robot to use the radius instead: + +## Rotate in Place Behavior +Using theRotation Shim Controller, a robot will simply rotate in place before starting to track a holonomic path. This allows a developer to tune a controller plugin to be optimized for path tracking and give you clean rotations, out of the box. +This was added due to quirks in some existing controllers whereas tuning the controller for a task can make it rigid – or the algorithm simply doesn’t rotate in place when working with holonomic paths (if that’s a desirable trait). The result is an awkward, stuttering, or whipping around behavior when your robot’s initial and path heading’s are significantly divergent. Giving a controller a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers (in one maintainer’s opinion). +Note: If using a non-holonomic, kinematically feasible planner (e.g. Smac Hybrid-A*, Smac State Lattice), this is not a necessary behavioral optimization. This class of planner will create plans that take into account the robot’s starting heading, not requiring any rotation behaviors. +This behavior is most optimially for: + +## Planner Plugin Selection +Nav2 provides a number of planning plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time). +In general though, the following table is a good guide for the optimal planning plugin for different types of robot bases: +If you are using a non-circular robot with very limited compute, it may be worth assessing the benefits of using one of the holonomic planners (e.g. particle assumption planners). It is the recommendation of the maintainers to start using one of the more advanced algorithms appropriate for your platformfirst, but to scale back the planner if need be. The run-time of the feasible planners are typically on par (or sometimes faster) than their holonomic counterparts, so don’t let the more recent nature of them fool you. +Since the planning problem is primarily driven by the robot type, the table accurately summarizes the advice to users by the maintainers. Within the circular robot regime, the choice of planning algorithm is dependent on application and desirable behavior. NavFn will typically make broad, sweeping curves; Theta* prefers straight lines and supports them at any angle; and Smac 2D is essentially a classical A* algorithm with cost-aware penalties. + +## Controller Plugin Selection +Nav2 provides a number of controller plugins out of the box. For a first-time setup, seeSetting Up Navigation Pluginsfor a more verbose breakdown of algorithm styles within Nav2, andNavigation Pluginsfor a full accounting of the current list of plugins available (which may be updated over time). +In general though, the following table is a good first-order description of the controller plugins available for different types of robot bases: +All of the above controllers can handle both circular and arbitrary shaped robots in configuration. +Regulated Pure Pursuit is good for exact path following and is typically paired with one of the kinematically feasible planners (eg State Lattice, Hybrid-A*, etc) since those paths are known to be drivable given hard physical constraints. However, it can also be applied to differential drive robots who can easily pivot to match any holonomic path. This is the plugin of choice if you simply want your robot to follow the path, rather exactly, without any dynamic obstacle avoidance or deviation. It is simple and geometric, as well as slowing the robot in the presence of near-by obstaclesandwhile making sharp turns. +DWB and MPPI are both options that will track paths, but also diverge from the path if there are dynamic obstacles present (in order to avoid them). DWB does this through scoring multiple trajectories on a set of critics. These trajectories are also generated via plugins that can be replaced, but support out of the box Omni and Diff robot types within the valid velocity and acceleration restrictions. These critics are plugins that can be selected at run-time and contain weights that may be tuned to create the desired behavior, such as minimizing path distance, minimizing distance to the goal or headings, and other action penalties that can be designed. This does require a bit of tuning for a given platform, application, and desired behavior, but it is possible to tune DWB to do nearly any single thing well. +MPPI on the other hand implements an optimization based approach, using randomly perturbed samples of the previous optimal trajectory to maximize a set of plugin-based objective functions. In that regard, it is similar to DWB however MPPI is a far more modern and advanced technique that will deal with dynamic agents in the environment and create intelligent behavior due to the optimization based trajectory planning, rather then DWB’s constant action model. MPPI however does have moderately higher compute costs, but it is highly recommended to go this route and has received considerable development resources and attention due to its power. This typically works pretty well out of the box, but to tune for specific behaviors, you may have to retune some of the parameters. The README.md file for this package contains details on how to tune it efficiently. +The Rotation Shim Plugin helps assist plugins like TEB and DWB (among others) to rotate the robot in place towards a new path’s heading before starting to track the path. This allows you to tune your local trajectory planner to operate with a desired behavior without having to worry about being able to rotate on a dime with a significant deviation in angular distance over a very small euclidean distance. Some controllers when heavily tuned for accurate path tracking are constrained in their actions and don’t very cleanly rotate to a new heading. Other controllers have a ‘spiral out’ behavior because their sampling requires some translational velocity, preventing it from simply rotating in place. This helps alleviate that problem and makes the robot rotate in place very smoothly. +Finally, Vector Pursuit is another good path tracking solution and just like RPP, is paired with a kinematically feasible planner. It is a bit more advanced than RPP in the sense it also takes path heading into account. Vector Pursuit can handle complex paths at high speeds, but it is still a simple geometric controller thus requiring low computation resources. + +## Caching Obstacle Heuristic in Smac Planners +Smac’s Hybrid-A* and State Lattice Planners provide an option,cache_obstacle_heuristic. This can be used to cache the heuristic to use between replannings to the same goal pose, which can increase the speed of the plannersignificantly(40-300% depending on many factors). The obstacle heuristic is used to steer the robot into the middle of spaces, respecting costs, and drives the kinematically feasible search down the corridors towards a valid solution. Think of it like a 2D cost-aware search to “prime” the planner about where it should go when it needs to expend more effort in the fully feasible search / SE2 collision checking. +This is useful to speed up performance to achieve better replanning speeds. However, if you cache this heuristic, it will not be updated with the most current information in the costmap to steer search. During planning, the planner will still make use of the newest cost information for collision checking,thusly this will not impact the safety of the path. However, it may steer the search down newly blocked corridors or guide search towards areas that may have new dynamic obstacles in them, which can slow things down significantly if entire solution spaces are blocked. +Therefore, it is the recommendation of the maintainers to enable this only when working in largely static (e.g. not many moving things or changes, not using live sensor updates in the global costmap, etc) environments when planning across large spaces to singular goals. Between goal changes to Nav2, this heuristic will be updated with the most current set of information, so it is not very helpful if you change goals very frequently. + +## Costmap2D Plugins +Costmap2D has a number of plugins that you can use (including the availability for you to create your own!). +In addition, costmap filters: +-KeepoutFilter: Marks keepout, higher weighted, or lower weighted zones in the costmap +-SpeedFilter: Reduces or increases robot speeds based on position +-BinaryFilter: Enables or disables a binary topic when in particular zones +Note: When the costmap filters can be paired with theVectorObjectserver to use vectorized zones rather than map rastered zones sharing the same software. + +## Nav2 Launch Options +Nav2’s launch files are made to be very configurable. Obviously for any serious application, a user should usenav2_bringupas the basis of their navigation launch system, but should be moved to a specific repository for a users’ work. A typical thing to do is to have a_navconfiguration package containing the launch and parameter files. +Withinnav2_bringup, there is a main entryfiletb3_simulation_launch.py. This is the main file used for simulating the robot and contains the following configurations: + +## Other Pages We’d Love To Offer +If you are willing to chip in, some ideas are inhttps://github.com/ros-navigation/docs.nav2.org/issues/204, but we’d be open to anything you think would be insightful! diff --git "a/exported_docs/nav2/TwirlingCritic\357\203\201.txt" "b/exported_docs/nav2/TwirlingCritic\357\203\201.txt" new file mode 100644 index 0000000..a53ca0b --- /dev/null +++ "b/exported_docs/nav2/TwirlingCritic\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: TwirlingCritic +URL: https://docs.nav2.org/configuration/packages/trajectory_critics/twirling.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. +: TwirlingCritic critic name defined in the.criticsparameter defined inDWB Controller. diff --git "a/exported_docs/nav2/UndockRobot\357\203\201.txt" "b/exported_docs/nav2/UndockRobot\357\203\201.txt" new file mode 100644 index 0000000..f0259bb --- /dev/null +++ "b/exported_docs/nav2/UndockRobot\357\203\201.txt" @@ -0,0 +1,25 @@ +Title: UndockRobot +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/UndockRobot.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Output Ports + + +## Example + + +Code Examples: + +Language: unknown +File: UndockRobot +``` + +``` diff --git "a/exported_docs/nav2/Using Collision Monitor\357\203\201.txt" "b/exported_docs/nav2/Using Collision Monitor\357\203\201.txt" new file mode 100644 index 0000000..357a380 --- /dev/null +++ "b/exported_docs/nav2/Using Collision Monitor\357\203\201.txt" @@ -0,0 +1,528 @@ +Title: Using Collision Monitor +URL: https://docs.nav2.org/tutorials/docs/using_collision_monitor.html#requirements +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to use a Collision Monitor with Nav2 stack. Based on this tutorial, you can setup it for your environment and needs. + +## Requirements +It is assumed ROS2 and Nav2 dependent packages are installed or built locally. +Please make sure that Nav2 project is also built locally as it was made inBuild and Install. + +## Configuring Collision Monitor +The Collision Monitor node has its owncollision_monitor_node.launch.pylaunch-file and preset parameters in thecollision_monitor_params.yamlfile for demonstration, though its trivial to add this to Nav2’s main launch file if being used in practice. +For the demonstration, two shapes will be created - an inner stop and a larger slowdown bounding boxes placed in the front of the robot: +If more than 3 points will appear inside a slowdown box, the robot will decrease its speed to30%from its value. +For the cases when obstacles are dangerously close to the robot, inner stop zone will work. +For this setup, the following lines should be added intocollision_monitor_params.yamlparameters file. Stop box is named asPolygonStopand slowdown bounding box - asPolygonSlow: +For the working configuration, at least one data source should be added. +In current demonstration, it is used laser scanner (thoughPointCloud2and Range/Sonar/IR sensors are also possible), which is described by the following lines for Collision Monitor node: +Set topic names, frame ID-s and timeouts to work correctly with a default Nav2 setup. +The wholenav2_collision_monitor/params/collision_monitor_params.yamlfile in this case will look as follows: + +## Configuring Collision Monitor with VelocityPolygon +For this part of tutorial, we will set up the Collision Monitor withVelocityPolygontype for astopaction.VelocityPolygonallows the user to setup multiple polygons to cover the range of the robot’s velocity limits. For example, the user can configure different polygons for rotation, moving forward, or moving backward. The Collision Monitor will check the robot’s velocity against each sub polygon to determine the appropriate polygon to be used for collision checking. +In general, here are the steps to configure the Collision Monitor withVelocityPolygontype: +In this example, we will consider anon-holonomicrobot with linear velocity limits of-1.0to1.0m/s and angular velocity limits of-1.0to1.0rad/s. Thelinear_minandlinear_maxparameters of the sub polygons should be set to the robot’s linear velocity limits, while thetheta_minandtheta_maxparameters should be set to the robot’s angular velocity limits. +Below is the example configuration using 4 sub-polygons to cover the full range of the robot’s velocity limits: +For holomic robots: +For holomic robots, theholonomicproperty should be set totrue. In this scenario, thelinear_minandlinear_maxparameters should cover the robot’s resultant velocity limits, while thetheta_minandtheta_maxparameters should cover the robot’s angular velocity limits. Additionally, there will be 2 more parameters,direction_start_angleanddirection_end_angle, to specify the resultant velocity direction. The covered direction will always span fromdirection_start_angletodirection_end_anglein thecounter-clockwisedirection. +Below shows some common configurations for holonomic robots that cover multiple directions of the resultant velocity: + +## Preparing Nav2 stack +The Collision Monitor is designed to operate below Nav2 as an independent safety node. +It acts as a filter for thecmd_velmessages from the controller to avoid potential collisions. +If no such zone is triggered, then thecmd_velmessage is used. +Else, it is scaled or set to stop as appropriate. +By default, the Collision Monitor is configured for usage with the Nav2 bringup package, running in parallel with thenavigation_launch.pylaunch file. For correct operation of the Collision Monitor with the Velocity Smoother, it is required to remove the Velocity Smoother’scmd_vel_smoothedremapping in thenavigation_launch.pybringup script as presented below. This will make the output topic of the Velocity Smoother to be untouched, which will be the input to the newly added Collision Monitor: +If you have changed Collision Monitor’s defaultcmd_vel_in_topicandcmd_vel_out_topicconfiguration, make sure Velocity Smoother’s default output topiccmd_vel_smoothedshould match to the input velocitycmd_vel_in_topicparameter value of the Collision Monitor node, and the output velocitycmd_vel_out_topicparameter value should be actualcmd_velto fit the replacement. + +## Demo Execution +Once Collision Monitor node has been tuned andcmd_veltopics adjusted, Collision Monitor node is ready to run. +For that, run Nav2 stack as written inGetting Started: +In parallel console, launch Collision Monitor node by using its launch-file: +Since bothPolygonStopandPolygonSlowpolygons will have their own publishers, they could be added to visualization as shown at the picture below: +Set the initial pose and then put Nav2 goal on map. +The robot will start its movement, slowing down while running near the obstacles, and stopping in close proximity to them: + +Code Examples: + +Language: unknown +File: PolygonSlow +``` +polygons +: +[ +"PolygonStop" +, +"PolygonSlow" +] +PolygonStop +: +type +: +"polygon" +points +: +"[[0.4, +0.3], +[0.4, +-0.3], +[0.0, +-0.3], +[0.0, +0.3]]" +action_type +: +"stop" +min_points +: +4 +# max_points: 3 for Humble +visualize +: +True +polygon_pub_topic +: +"polygon_stop" +PolygonSlow +: +type +: +"polygon" +points +: +"[[0.6, +0.4], +[0.6, +-0.4], +[0.0, +-0.4], +[0.0, +0.4]]" +action_type +: +"slowdown" +min_points +: +4 +# max_points: 3 for Humble +slowdown_ratio +: +0.3 +visualize +: +True +polygon_pub_topic +: +"polygon_slowdown" +``` + +Language: unknown +File: PointCloud2 +``` +observation_sources +: +[ +"scan" +] +scan +: +type +: +"scan" +topic +: +"scan" +``` + +Language: unknown +File: nav2_collision_monitor/params/collision_monitor_params.yaml +``` +collision_monitor +: +ros__parameters +: +use_sim_time +: +True +base_frame_id +: +"base_footprint" +odom_frame_id +: +"odom" +cmd_vel_in_topic +: +"cmd_vel_smoothed" +cmd_vel_out_topic +: +"cmd_vel" +transform_tolerance +: +0.5 +source_timeout +: +5.0 +stop_pub_timeout +: +2.0 +enable_stamped_cmd_vel +: +True +# False for Jazzy or older by default +polygons +: +[ +"PolygonStop" +, +"PolygonSlow" +] +PolygonStop +: +type +: +"polygon" +points +: +"[[0.4, +0.3], +[0.4, +-0.3], +[0.0, +-0.3], +[0.0, +0.3]]" +action_type +: +"stop" +min_points +: +4 +# max_points: 3 for Humble +visualize +: +True +polygon_pub_topic +: +"polygon_stop" +PolygonSlow +: +type +: +"polygon" +points +: +"[[0.6, +0.4], +[0.6, +-0.4], +[0.0, +-0.4], +[0.0, +0.4]]" +action_type +: +"slowdown" +min_points +: +4 +# max_points: 3 for Humble +slowdown_ratio +: +0.3 +visualize +: +True +polygon_pub_topic +: +"polygon_slowdown" +observation_sources +: +[ +"scan" +] +scan +: +type +: +"scan" +topic +: +"scan" +``` + +Language: unknown +File: theta_max +``` +polygons +: +[ +"VelocityPolygonStop" +] +VelocityPolygonStop +: +type +: +"velocity_polygon" +action_type +: +"stop" +min_points +: +6 +visualize +: +True +enabled +: +True +polygon_pub_topic +: +"velocity_polygon_stop" +velocity_polygons +: +[ +"rotation" +, +"translation_forward" +, +"translation_backward" +, +"stopped" +] +holonomic +: +false +rotation +: +points +: +"[[0.3, +0.3], +[0.3, +-0.3], +[-0.3, +-0.3], +[-0.3, +0.3]]" +linear_min +: +0.0 +linear_max +: +0.05 +theta_min +: +-1.0 +theta_max +: +1.0 +translation_forward +: +points +: +"[[0.35, +0.3], +[0.35, +-0.3], +[-0.2, +-0.3], +[-0.2, +0.3]]" +linear_min +: +0.0 +linear_max +: +1.0 +theta_min +: +-1.0 +theta_max +: +1.0 +translation_backward +: +points +: +"[[0.2, +0.3], +[0.2, +-0.3], +[-0.35, +-0.3], +[-0.35, +0.3]]" +linear_min +: +-1.0 +linear_max +: +0.0 +theta_min +: +-1.0 +theta_max +: +1.0 +# This is the last polygon to be checked, it should cover the entire range of robot's velocities +# It is used as the stopped polygon when the robot is not moving and as a fallback if the velocity +# is not covered by any of the other sub-polygons +stopped +: +points +: +"[[0.25, +0.25], +[0.25, +-0.25], +[-0.25, +-0.25], +[-0.25, +0.25]]" +linear_min +: +-1.0 +linear_max +: +1.0 +theta_min +: +-1.0 +theta_max +: +1.0 +``` + +Language: unknown +File: navigation_launch.py +``` +Node +( +package += +'nav2_velocity_smoother' +, +executable += +'velocity_smoother' +, +name += +'velocity_smoother' +, +output += +'screen' +, +respawn += +use_respawn +, +respawn_delay += +2.0 +, +parameters += +[ +configured_params +], +arguments += +[ +'--ros-args' +, +'--log-level' +, +log_level +], +remappings += +remappings ++ +- +[( +'cmd_vel' +, +'cmd_vel_nav' +), +( +'cmd_vel_smoothed' +, +'cmd_vel' +)]), ++ +[( +'cmd_vel' +, +'cmd_vel_nav' +)]), +... +ComposableNode +( +package += +'nav2_velocity_smoother' +, +plugin += +'nav2_velocity_smoother::VelocitySmoother' +, +name += +'velocity_smoother' +, +parameters += +[ +configured_params +], +remappings += +remappings ++ +- +[( +'cmd_vel' +, +'cmd_vel_nav' +), +( +'cmd_vel_smoothed' +, +'cmd_vel' +)]), ++ +[( +'cmd_vel' +, +'cmd_vel_nav' +)]), +``` + +Language: unknown +File: cmd_vel +``` +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +headless: += +False + +``` + +Language: unknown +File: cmd_vel +``` +ros2 +launch +nav2_collision_monitor +collision_monitor_node.launch.py + +``` diff --git "a/exported_docs/nav2/Using Docking Server\357\203\201.txt" "b/exported_docs/nav2/Using Docking Server\357\203\201.txt" new file mode 100644 index 0000000..3af2661 --- /dev/null +++ "b/exported_docs/nav2/Using Docking Server\357\203\201.txt" @@ -0,0 +1,655 @@ +Title: Using Docking Server +URL: https://docs.nav2.org/tutorials/docs/using_docking.html#overview +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to use the Docking Server with Nav2 robot systems. +The Docking Server is a general framework which can be used with arbitrary types of robots and docks in order to auto-dock them. +This is accomplished via pluginsChargingDockandNonChargingDockwhich implement the dock specifics like detecting the pose of the dock using sensor data, how to detect when the robot is in contact with the dock, and when charging has successfully started. +A configuration of the docking server can contain a database of many docks of different pluginChargingDockandNonChargingDocktypes to handle a broad range of docking locations and hardware dock revisions. +Included with the package is an exampleSimpleChargingDockandSimpleNonChargingDockplugins which contains features and methods very common for robot docking. +These support charging stations and docking with static infrastructure (ex. conveyor belts) or dynamic docking (ex pallets) locations. +It is likely that you may be able to use this as well rather than developing your own dock plugin to get started. +The docking procedure is as follows: +Thanks to NVIDIA for sponsoring this Docking Server package and this tutorial! +You can find how to dock your Nova Carter robot using Nav2 and this work in thenova_carter_docking package! + +## Requirements +It is assumed ROS2 and Nav2 dependent packages are installed or built locally - includingopennav_docking. +Please make sure that Nav2 project is also built locally, seeBuild and Installfor reference. +Seeopennav_dockingREADME for complete concept explanations, parameters, and APIs. + +## ChargingDock Plugins +opennav_docking_core::ChargingDockandopennav_docking_core::ChargingDockplugins are established to abstract out robot- and dock-specifics from the generalized framework. +This allows a system to leverage this framework and provide its own methods for detecting the dock’s current pose, when the robot is charging, and when contact is made. +Luckily, there are several common ROS APIs that allow us to create semi-generalizedSimpleChargingDockandSimpleNonChargingDockplugins that allows out-of-the-box docking as long as users provideJointState,BatteryState, and detected dock posePoseStampedtopics. +However, one way or another, your system requires an applicableChargingDockorNonChargingDockplugin for each type of dock you wish to use. +The plugins has a few key APIs: +TheSimpleChargingDockprovides an implementation with common options for these APIs: +Thus, for testing (no detection, no battery information, no joint state information) and realistic application (dock detection, battery status information, joint state information), this dock plugin can be used. +It can also be used when only some of the information if available as well. +If your robot or dock does not fall into these implementations (i.e. using custom battery or detection messages that cannot be converted into ROS standard types), then you may be required to build your own plugin to meet your particular needs. +However, you can use theSimpleChargingDockassuming you turn off these settings and dock blind to get started. +There is an equivalentSimpleNonChargingDockplugin for non-charging docking needs. +If you do not currently have a way to detect your dock, dock detection can be done easily using Apriltags and theisaac_ros_apriltagorROS image_procnodes to get started. +Use the Isaac ROS if using a Jetson platform to obtain a GPU optimized pipeline with your camera feeds. +The defaults support this out of the box, seenova_carter_dockingfor an example. + +## Dock Database +To dock your robot, you must provide the set of docks in your environment you’d like to utilize. +This is done in the docking server via theDock Databasewhich contains the set of docks, their instance types, and a set of shared plugins. +The plugins are separated from the dock instances so that many instances can share the same plugin to save on memory and networking overhead when potentially dozens or more docks exist in a space. +The docks plugins must be provided in your docking server’s configuration file. +However, the dock instance may be provided either in the configuration fileorwithin a provided filepath to decouple the server’s configuration from a particular application environment. +The example below shows an inline configuration of the docking plugins and dock instances where one dock type (nova_carter_dock) is specified with 3 individual instances: a home dock, and 2 general shared fallback docks. +The docks can be specified as[x,y,theta]in any reference frame you like, as long as TF is aware of them. +Please update these with your own docking plugin and dock locations in your map. +The analog of this is shown below as an independentdock_database.yamlwhich can be provided to thedocking_servervia thedock_databaseparameter. +Note that you are required to provide at least 1 dock plugin and 1 dock instance. +The Docking Server’s Action API can take in a dock’s instance information separately to bypass the database, but its plugin must exist in the server’s configuration. +If you plan to only use this API, you can set adummy_dock. +Generally speaking, its wise to set your docks in the database and use the Docking Server’s API to dock at an instance’s Dock ID to decouple the semantic information about docks from the action request (requiring your application instead to have all of the docks’ locations), but bypassing the database can be useful for testing and movable docking targets. +The dock poses in the map can be annotated using your favorite map editing tools, obtained by/clicked_pointin rviz2, or measured location. + +## Configuring Docking Server +Now that we have both a plugin for interacting with a dock and specified the locations of docks in your map, we’re ready to configure the docking server. +For this example, we’re going to use the Nvidia-Segway Nova Carter Robot and you can find the source code of this demo in thenova_carter_dockingpackage. +For a full list of parameters and their descriptions, check out theDocking Server. +Below is an example configuration used by the Nova Carter robot. +Notable is the setting of thefixed_frametoodom, notmapin order to decouple localization error from the docking procedure. +We also use one dock pluginnova_carter_dockfor allNdocks specified in thedock_databasefile. +The simple charging dock plugin uses a 70cm staging offset from the dock’s database pose for staging. +This staging pose is selected as close enough to detect the dock but far enough away to give maneuvering space to account for expected dock movement or localization error. +Sinceuse_stall_detectionfor theJointStatesisfalse, we are considered successfully docked once we’re withindocking_threshold(5cm) to the docking pose. +This docking pose is specified as the detected pose with theexternal_detection_*offsets applied to account for the robot’s intended docking pose relative to the detected feature. +In this example, Apriltags are used, so we apply the rotations to the Apriltag detected frame and a-0.18translational offset to account for the pose the robot should be in when docked relative to the tag’s pose. +Sinceuse_external_detection_poseanduse_battery_statusare both enabled, we use both detected dock poses (apriltag) and battery state information for determining if we’re charging. +The maximum speed is 15 cm/s to slowly and carefully back into the dock and we’ll retry docking 3x in case charging is not detected or we lose detected dock tracks during the attempt. + +## Adding Docking Server to Launch +This server can now be added to your launch file with the path to this parameter file for use (or added to your main shared configuration file). + +## Docking Action API +The API for docking and undocking is comparatively simple. +TheDockRobotaction consists of two main modalities: using the dock database or specifying a dock to use in the action. +If using the database, setuse_dock_id=True(default) and you only need to specify thedock_idyou wish to use, such ashome_dock,flex_dock1, or whatever dock instance you like. +If bypassing the database,use_dock_idmust be set to false anddock_pose,dock_typemust be fully specified to make up for the lack of entry metadata in the database. +This requires the action caller to know about all of the docks, rather than pushing that into the Docking Server’s database, which is not recommended. +Optionally, you can disable using Nav2 to navigate to the staging pose if outside of the pre-staging tolerance usingnavigate_to_staging_pose=Falseor set the maximum time for staging navigationmax_staging_time. +In result, you obtain if the action was successful, if it wasn’t what the error code was, and the total number of retries attempted. +During execution, feedback is provided on the current docking state - which is published irregularly only when an event occurs. It contains the state, the current total elapsed duration of attempted docking, and the current number of retries. +The feedback can be obtained from your action client if this information is useful to your application. +TheUndockRobotaction is even simpler. There are no required goal fields exceptdock_typeif undocking is being called when the server’s instance did not dock the robot to store its current state information (such as after a restart on the dock). +It contains no feedback and returns thesuccessstate and theerror_codeif a problem occurs. + +## Putting It All Together +At this point, if you haven’t already, create your dock plugin (or useSimpleChargingDock), configuration file, and launch file - along with any other nodes required like apriltags or other detectors. +You can see an example package used in this tutorial in thenova_carter_dockingpackage, which contains a configuration file and launch file containing the apriltags detector andPoseStampedpose publisher. +If you’re interested in using Apriltags and an Nvidia Jetson, you can find the tags we used in themedia/directory and the launch fileisaac_apriltag_detection_pipeline.launch.pywhich sets it all up for you. +If not using the Jetson, you can replace the Isaac ROS apriltag detector withimage_proc. +We can test this using the scriptdemo.pyinnova_carter_docking’s root directory. +It will set the robot’s pose as virtually the dock’s staging pose to bypass navigating to the staging pose and attempt docking immediately, then infinitely loop docking and undocking in a row. +This is a useful first-time setup to try docking, refine your detection offsets, and obtain reliability metrics of your complete system. +See the video below of this all at work! +Note that the robot is able to overcome: +This script demonstrates the essential use of the Docking Server. +However, it does not use the dock database of pre-mapped dock locations that you setup. +After you launch Nav2 and localize your robot in your map, we can adjustdockRobot()to take in your desireddock_idand perform docking instead: +Then, we can see the full docking system in action in a non-trivial environment! +Depending on your robot’s relative pose to the dock and your pre-staging tolerance settings, Nav2 may attempt to navigate to the staging pose before docking. +If you wish to disable that, setgoal_msg.navigate_to_staging_pose=Falseand then Docking will trigger immediately. +You can see both of these in action in the video above. +Don’t want to call Docking Server from a script Python or C++ script and want to use it in your Autonomous Behavior Tree? Seeopennav_docking_btforDockRobot,UndockRobotBehavior Tree nodes to call the Docking Server from your application behavior tree – with a providedXMLexample. +Note that if usingnavigate_to_staging_pose=True, you cannot callDockRobotfrom inside a Nav2 Behavior Tree, only from your higher level autonomy tree since it recursively calls Nav2. +If you wish to callDockRobotfrom inside your Nav2 BT, you must roughly pre-stage the robot near the dock first (which should be easy as a navigation goal). +However, you can always callUndockRobotfrom any behavior tree! +Happy docking! + +Code Examples: + +Language: unknown +File: [x,y,theta] +``` +docking_server +: +ros__parameters +: +# Types of docks +dock_plugins +: +[ +'nova_carter_dock' +] +nova_carter_dock +: +plugin +: +'opennav_docking::SimpleChargingDock' +# More parameters exist here that we will discuss later in the tutorial +# Dock instances +docks +: +[ +'home_dock' +, +'flex_dock1' +, +'flex_dock2' +] +home_dock +: +type +: +'nova_carter_dock' +frame +: +map +pose +: +[ +0.0 +, +0.0 +, +0.0 +] +flex_dock1 +: +type +: +'nova_carter_dock' +frame +: +map +pose +: +[ +10.0 +, +10.0 +, +0.0 +] +flex_dock2 +: +type +: +'nova_carter_dock' +frame +: +map +pose +: +[ +30.0 +, +30.0 +, +0.0 +] +# Or use +# dock_database: /my/path/to/dock_database.yaml +``` + +Language: unknown +File: dock_database +``` +docks +: +home_dock +: +type +: +"nova_carter_dock" +frame +: +"map" +pose +: +[ +0.0 +, +0.0 +, +0.0 +] +flex_dock1 +: +type +: +"nova_carter_dock" +frame +: +"map" +pose +: +[ +10.0 +, +10.0 +, +0.0 +] +flex_dock2 +: +type +: +"nova_carter_dock" +frame +: +"map" +pose +: +[ +20.0 +, +20.0 +, +0.0 +] +``` + +Language: unknown +File: use_battery_status +``` +docking_server +: +ros__parameters +: +controller_frequency +: +50.0 +initial_perception_timeout +: +5.0 +wait_charge_timeout +: +5.0 +dock_approach_timeout +: +30.0 +undock_linear_tolerance +: +0.05 +undock_angular_tolerance +: +0.1 +max_retries +: +3 +base_frame +: +"base_link" +fixed_frame +: +"odom" +dock_backwards +: +false +dock_prestaging_tolerance +: +0.5 +# Types of docks +dock_plugins +: +[ +'nova_carter_dock' +] +nova_carter_dock +: +plugin +: +'opennav_docking::SimpleChargingDock' +docking_threshold +: +0.05 +staging_x_offset +: +-0.7 +use_external_detection_pose +: +true +use_battery_status +: +true +use_stall_detection +: +false +external_detection_timeout +: +1.0 +external_detection_translation_x +: +-0.18 +external_detection_translation_y +: +0.0 +external_detection_rotation_roll +: +-1.57 +external_detection_rotation_pitch +: +-1.57 +external_detection_rotation_yaw +: +0.0 +filter_coef +: +0.1 +# Sep. file of dock instances so config file can be used in multiple locations +dock_database +: +/my/path/to/dock_database.yaml +controller +: +k_phi +: +3.0 +k_delta +: +2.0 +v_linear_min +: +0.15 +v_linear_max +: +0.15 +``` + +Language: unknown +File: use_battery_status +``` +nova_carter_dock_params_dir += +os +. +path +. +join +( +get_package_share_directory +( +'nova_carter_docking' +), +'params' +) +params_file += +default_value += +os +. +path +. +join +( +nova_carter_dock_params_dir +, +'nova_carter_docking.yaml' +) +docking_server += +Node +( +package += +'opennav_docking' +, +executable += +'opennav_docking' +, +name += +'docking_server' +, +output += +'screen' +, +parameters += +[ +params_file +], +) +``` + +Language: unknown +File: max_staging_time +``` +#goal definition + +bool +use_dock_id +True +# Whether to use the dock_id or dock_pose fields + +string +dock_id +# Dock name or ID to dock at, from given dock database + + +geometry_msgs/PoseStamped +dock_pose +# Dock pose + +string +dock_type +# If using dock_pose, what type of dock it is. Not necessary if only using one type of dock. + + +float32 +max_staging_time +1000 +.0 +# Maximum time for navigation to get to the dock's staging pose. + +bool +navigate_to_staging_pose +True +# Whether or not to navigate to staging pose or assume robot is already at staging pose within tolerance to execute behavior + + +--- + +#result definition + +bool +success +True +# docking success status + +uint16 +error_code +0 +# Contextual error code, if any + +uint16 +num_retries +0 +# Number of retries attempted + + +--- + +#feedback definition + +uint16 +state +# Current docking state + +builtin_interfaces/Duration +docking_time +# Docking time elapsed + +uint16 +num_retries +0 +# Number of retries attempted +``` + +Language: unknown +File: error_code +``` +#goal definition + +string +dock_type +float32 +max_undocking_time +30 +.0 +# Maximum time to undock + + +--- + +#result definition + +bool +success +True +# docking success status + +uint16 +error_code +0 +# Contextual error code, if any + + +--- + +#feedback definition +``` + +Language: unknown +File: dock_id +``` +def +dockRobot +( +self +, +dock_id += +"" +): +"""Send a `DockRobot` action request.""" +print +( +"Waiting for 'DockRobot' action server" +) +while +not +self +. +docking_client +. +wait_for_server +( +timeout_sec += +1.0 +): +print +( +'"DockRobot" action server not available, waiting...' +) +goal_msg += +DockRobot +. +Goal +() +goal_msg +. +use_dock_id += +True +goal_msg +. +dock_id += +dock_id +# if wanting to use ID instead +print +( +'Docking at ID: ' ++ +str +( +dock_id +) ++ +'...' +) +send_goal_future += +self +. +docking_client +. +send_goal_async +( +goal_msg +, +self +. +_feedbackCallback +) +rclpy +. +spin_until_future_complete +( +self +, +send_goal_future +) +self +. +goal_handle += +send_goal_future +. +result +() +if +not +self +. +goal_handle +. +accepted +: +print +( +'Docking request was rejected!' +) +return +False +self +. +result_future += +self +. +goal_handle +. +get_result_async +() +return +True +... +dock_id += +'home_dock' +tester +. +dockRobot +( +dock_id +) +``` diff --git "a/exported_docs/nav2/Using Rotation Shim Controller\357\203\201.txt" "b/exported_docs/nav2/Using Rotation Shim Controller\357\203\201.txt" new file mode 100644 index 0000000..bfac7c5 --- /dev/null +++ "b/exported_docs/nav2/Using Rotation Shim Controller\357\203\201.txt" @@ -0,0 +1,170 @@ +Title: Using Rotation Shim Controller +URL: https://docs.nav2.org/tutorials/docs/using_shim_controller.html#demo-execution +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial will discuss how to set up your robot to use theRotationShimControllerto help create intuitive, rotate-in-place, behavior for your robot while starting out to track a path. The goal of this tutorial is to explain to the reader the value of the controller, how to configure it, how to configure the primary controller with it, and finally an example of it in use. +Before starting this tutorial, completing theGetting Startedis highly recommended especially if you are new to ROS and Nav2. The requirements are having the latest install of Nav2 / ROS 2 containing this package. + +## What is the Rotation Shim Controller? +This was developed due to quirks in TEB and DWB, but applicable to any other controller plugin type that you’d like to have rotation in place behavior with.TEB’s behavior tends to whip the robot around with small turns, or when the path is starting at a very different heading than current, in a somewhat surprising way due to the elastic band approach.DWBcan be tuned to have any type of behavior, but typically to tune it to be an excellent path follower also makes it less optimally capable of smooth transitions to new paths at far away headings – there are always trade offs. Giving both TEB and DWB a better starting point to start tracking a path makes tuning the controllers significantly easier and creates more intuitive results for on-lookers. +Note that it is not required to use this withanyplugin. Many users are perfectly successful without using this controller, but if a robot may rotate in place before beginning its path tracking task (or others), it can be advantageous to do so. +Thenav2_rotation_shim_controllerwill check the rough heading difference with respect to the robot and a newly received path. If within a threshold, it will pass the request onto theprimary_controllerto execute the task. If it is outside of the threshold, this controller will rotate the robot in place towards that path heading. Once it is within the tolerance, it will then pass off control-execution from this rotation shim controller onto the primary controller plugin. At this point, the robot’s main plugin will take control for a smooth hand off into the task. +TheRotationShimControlleris most suitable for: + +## Configuring Rotation Shim Controller +This controller is ashimbecause it is placed between the primary controller plugin and the controller server. It takes commands and pre-processes them to rotate to the heading and then passes off execution-control to the primary plugin once that condition is met - acting as a simple pass through. +As such, its configuration looks very similar to that of any other plugin. In the code block below, you can see that we’ve added theRotationShimControlleras the plugin for path tracking in the controller server. You can see that we’ve also configured it below with its internal parameters,angular_dist_thresholdthroughmax_angular_accel. +The Rotation Shim Controller is very simple and only has a couple of parameters to dictate the conditions it should be enacted. + +## Configuring Primary Controller +There is one more remaining parameter of theRotationShimControllernot mentioned above, theprimary_controller. This is the type of controller that your application would like to use as the primary modus operandi. It will share the same name and yaml namespace as the shim plugin. You can observe this below with the primary controller set theDWB(with the progress and goal checkers removed for brevity). +An important note is thatwithin the same yaml namespace, you may also include anyprimary_controllerspecific parameters required for a robot. Thusly, aftermax_angular_accel, you can include any ofDWB’s parameters for your platform. + +## Demo Execution + + +Code Examples: + +Language: unknown +File: max_angular_accel +``` +controller_server +: +ros__parameters +: +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +progress_checker_plugins +: +[ +"progress_checker" +] +# progress_checker_plugin: "progress_checker" For Humble and older +goal_checker_plugins +: +[ +"goal_checker" +] +controller_plugins +: +[ +"FollowPath" +] +progress_checker +: +plugin +: +"nav2_controller::SimpleProgressChecker" +required_movement_radius +: +0.5 +movement_time_allowance +: +10.0 +goal_checker +: +plugin +: +"nav2_controller::SimpleGoalChecker" +xy_goal_tolerance +: +0.25 +yaw_goal_tolerance +: +0.25 +stateful +: +True +FollowPath +: +plugin +: +"nav2_rotation_shim_controller::RotationShimController" +angular_dist_threshold +: +0.785 +forward_sampling_distance +: +0.5 +rotate_to_heading_angular_vel +: +1.8 +max_angular_accel +: +3.2 +simulate_ahead_time +: +1.0 +``` + +Language: unknown +File: DWB +``` +controller_server +: +ros__parameters +: +use_sim_time +: +True +controller_frequency +: +20.0 +min_x_velocity_threshold +: +0.001 +min_y_velocity_threshold +: +0.5 +min_theta_velocity_threshold +: +0.001 +controller_plugins +: +[ +"FollowPath" +] +FollowPath +: +plugin +: +"nav2_rotation_shim_controller::RotationShimController" +primary_controller +: +"dwb_core::DWBLocalPlanner" +angular_dist_threshold +: +0.785 +forward_sampling_distance +: +0.5 +rotate_to_heading_angular_vel +: +1.8 +max_angular_accel +: +3.2 +simulate_ahead_time +: +1.0 +# DWB parameters +... +... +... +``` diff --git "a/exported_docs/nav2/Using VIO to Augment Robot Odometry\357\203\201.txt" "b/exported_docs/nav2/Using VIO to Augment Robot Odometry\357\203\201.txt" new file mode 100644 index 0000000..8a53164 --- /dev/null +++ "b/exported_docs/nav2/Using VIO to Augment Robot Odometry\357\203\201.txt" @@ -0,0 +1,157 @@ +Title: Using VIO to Augment Robot Odometry +URL: https://docs.nav2.org/tutorials/docs/integrating_vio.html#overview +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial highlights how to setup Visual-Inerial Odometry (VIO) into a Nav2 and ROS 2 based robotics system to augment robot odometry. +Many modern robotics platforms have unideal configurations for high quality wheel odometry. For example, skid-steer, tracked, omnidirectional robots using mecanum wheels, and legged robots are notorious for producing suboptimal odometry. These types of platforms are becoming increasingly common in the robotics landscape and require augmentations or replacement sources of odometry. Further, some applications of robotics technologies involve retrofitting existing equipment which may not have odometry altogether. +A subfield of computer vision and robotics focuses on how to use Visual (e.g. camera) and Inertial (e.g. IMU) data in order to compute high-speed relative motion independent of robot mechanics. This is an especially useful technology for UAVs without accurate intrinsic odometric sensing capabilities – or mobile robots with poor interinsic odometry measurements. +Thus, this tutorial walks through the integration of VIO into a robot system to replace or augment wheel odometry so that your robot can autonomously navigate with quality state estimation required for a well-engineered system that is able to accurately and predictably complete its tasks. +Throughout this tutorial, we will be using theStereolabsSDK’sPosition Trackingcapability as our VIO solution of choice paired with the newZED Xcamera. This VIO solution is easy to use and provides production-quality performance forfreewhen using a ZED camera module. + +## Setting Up the ZED X Camera +We’re using the ZED X for the purposes of this tutorial due to its: +Though, any other ZED camera with an IMU in it will work as well (ZED2, ZED2i, ZED mini, etc). If you are using the ZED X in particular, checkoutthis playlist on YouTube showing step by step how to setup the Nvidia Jetson and ZED X for ROS 2orZED X Getting Started pageto install the SDK, ZED X drivers, and ROS 2 drivers needed to proceed. +At this point, you should be able to run one of the following commands to launch the driver and visualize the sensor data in Rviz. Note that these are ROS 2 component nodes that also may be loaded into your system’s component manager to minimize latency due to serialization. +As of September 2023, the driver out of the box produces the fullmap->odom->base_link->cameratree on its own. This is since the Pose SDK can produce not only VIO, but loop-closure VSLAM representing the full state estimation TF tree. +We want to be able to fuse in other information such as an external IMU, wheel odometry, GPS, or other sensors into our local or global state estimates, so we need to disable TF publication ofmap->odomandodom->base_linkto be provided by our fused outputs. Especially considering the ZED X camera knows nothing about the nature of thebase_linkframe. However, if you would like to use the ZED’s state estimate for your entire system without further sensor fusion, you certainly can! + +## Setting Up ZED ROS +In order to run VIO alone, we need to do the following: +Thus, make the following parameter updates to thezed_wrapper’s default parameters: +Optionally, remap the zedodomtopic to a topic that isn’t reserved or commonly used by other systems. In your ZED launch file add to the node / launch file: + +## Fusing VIO Into Local State Estimate +Now that we have the ZED ROS 2 drivers set up to publish our VIO to a topic and leave our TF tree to the fusion algorithm and Robot State Publisher (e.g. URDF), we’re finally ready to fuse in VIO into our broader state estimate using therobot_localizationpackage. +This package is a generalized EKF and UKF solution to state estimation of potentially many different topics, publishing at different rates, of different types. If you’re unfamiliar withrobot_localizationcheckout ourFirst-Time Robot Setup Guide’s Odometry page for basic information and thepackage’s extensive documentation. +Most users at this point already have arobot_localizationconfiguration file in their robot systems to fuse existing sensors together, such as wheel odometry (even poor) and robot IMUs. We’ll be adding a new odom field,odom1, to our configuration to fuse in VIO’s position and orientation into our filter. If this is your first odometry field, useodom0and you can base your file onekf.yaml. +Make sure to evaluate your EKF’sfrequency,two_d_mode,publish_tf, and key frames to be appropriate for your application. We generally want to publish TF and have 2D mode on when navigating in flat indoor environments only. + +## Fusing VSLAM Into Global State Estimate +While out of the scope of this tutorial, it is possible to continue to produce VSLAM results for global localization with loop closure (both in general and using the Stereolabs Position Tracking SDK). The steps for integration are similar to the last sections, except: + +## Testing it Out! +In the below example, we’re fusing the Stereolabs SDK’s Pose Tracking VIO solution with a robot’s external IMU and odometry (e.g.robot_localizationhasodom0odom1andimu0) to improve performance while navigating on a legged robot platform in outdoor environments. The robot’s internal odometry based on leg motion is quite poor and causes the robot to have generally poor autonomous navigation performance. +The Visual-Inertial Odometry’s error over these datasets is 4.1% over the 70m path. Typically for ‘good’ odometry from wheel encoders + IMU, I would like to see 2-3% fully tuned (or less than 1% for ‘great’ odometry), so this is a great source! Fused in with the legged robot odometry, it improves overall performance to an acceptable level! + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` +$ +ros2 +launch +zed_wrapper +zedx.launch.py +$ +ros2 +launch +zed_wrapper +zedxm.launch.py + +``` + +Language: unknown +File: zed_wrapper +``` +pos_tracking +: +publish_tf +: +false +# Disables odom -> base_link TF transformation +publish_map_tf +: +true +# Disables map -> odom TF transformation +area_memory +: +false +# Disables loop closure computation, but Pose topic for global VSLAM still published (but now pure VIO) +# Optional optimizations +two_d_mode +: +false +# Or true, up to you! +pos_tracking_enabled +: +true +# of course! +path_max_count +: +30 +qos_depth +: +5 +``` + +Language: unknown +File: odom +``` +remappings += +[( +'odom' +, +'camera_odom' +)] +``` + +Language: unknown +File: odom0 +``` +odom1 +: +camera_odom +# Adjust if namespacing ZED camera (e.g. /zed/odom) +odom1_config +: +[ +true +, +true +, +true +, +# X, Y, Z +true +, +true +, +true +, +# Roll, Pitch, Yaw +false +, +false +, +false +, +# Vx, Vy, Vz +false +, +false +, +false +, +# Vroll, Vpitch, Vyaw +false +, +false +, +false +] +# Ax, Ay, Az +odom1_differential +: +false +odom1_relative +: +true +odom1_queue_size +: +2 +``` diff --git "a/exported_docs/nav2/Velocity Smoother\357\203\201.txt" "b/exported_docs/nav2/Velocity Smoother\357\203\201.txt" new file mode 100644 index 0000000..84b7c7e --- /dev/null +++ "b/exported_docs/nav2/Velocity Smoother\357\203\201.txt" @@ -0,0 +1,91 @@ +Title: Velocity Smoother +URL: https://docs.nav2.org/configuration/packages/configuring-velocity-smoother.html#velocity-smoother-parameters +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Velocity Smoother Parameters + + +## Example + + +Code Examples: + +Language: unknown +File: TwistStamped +``` +velocity_smoother +: +ros__parameters +: +smoothing_frequency +: +20.0 +scale_velocities +: +false +feedback +: +"OPEN_LOOP" +max_velocity +: +[ +0.5 +, +0.0 +, +2.5 +] +min_velocity +: +[ +-0.5 +, +0.0 +, +-2.5 +] +deadband_velocity +: +[ +0.0 +, +0.0 +, +0.0 +] +velocity_timeout +: +1.0 +max_accel +: +[ +2.5 +, +0.0 +, +3.2 +] +max_decel +: +[ +-2.5 +, +0.0 +, +-3.2 +] +odom_topic +: +"odom" +odom_duration +: +0.1 +use_realtime_priority +: +false +enable_stamped_cmd_vel +: +false +``` diff --git "a/exported_docs/nav2/Voxel Layer Parameters\357\203\201.txt" "b/exported_docs/nav2/Voxel Layer Parameters\357\203\201.txt" new file mode 100644 index 0000000..5963d8c --- /dev/null +++ "b/exported_docs/nav2/Voxel Layer Parameters\357\203\201.txt" @@ -0,0 +1,5 @@ +Title: Voxel Layer Parameters +URL: https://docs.nav2.org/configuration/packages/costmap-plugins/voxel.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/nav2/WaitAtWaypoint\357\203\201.txt" "b/exported_docs/nav2/WaitAtWaypoint\357\203\201.txt" new file mode 100644 index 0000000..97e5d46 --- /dev/null +++ "b/exported_docs/nav2/WaitAtWaypoint\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: WaitAtWaypoint +URL: https://docs.nav2.org/configuration/packages/nav2_waypoint_follower-plugins/wait_at_waypoint.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: nav2_waypoint_follower plugin name defined in thewaypoint_task_executor_plugin_idparameter inWaypoint Follower. diff --git "a/exported_docs/nav2/Wait\357\203\201.txt" "b/exported_docs/nav2/Wait\357\203\201.txt" new file mode 100644 index 0000000..c7a344b --- /dev/null +++ "b/exported_docs/nav2/Wait\357\203\201.txt" @@ -0,0 +1,26 @@ +Title: Wait +URL: https://docs.nav2.org/configuration/packages/bt-plugins/actions/Wait.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Ports + + +## Example + + +Code Examples: + +Language: unknown +File: use_cancel_deceleration +``` + +``` diff --git "a/exported_docs/nav2/Waypoint Follower\357\203\201.txt" "b/exported_docs/nav2/Waypoint Follower\357\203\201.txt" new file mode 100644 index 0000000..cf6c8de --- /dev/null +++ "b/exported_docs/nav2/Waypoint Follower\357\203\201.txt" @@ -0,0 +1,71 @@ +Title: Waypoint Follower +URL: https://docs.nav2.org/configuration/packages/configuring-waypoint-follower.html#parameters +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters + + +## Provided Plugins + + +## Default Plugin + + +## Example + + +Code Examples: + +Language: unknown +File: plugin +``` +waypoint_follower +: +ros__parameters +: +waypoint_task_executor_plugin +: +"wait_at_waypoint" +wait_at_waypoint +: +plugin +: +"nav2_waypoint_follower::WaitAtWaypoint" +enabled +: +True +waypoint_pause_duration +: +0 +``` + +Language: unknown +File: nav2_waypoint_follower +``` +waypoint_follower +: +ros__parameters +: +loop_rate +: +20 +stop_on_failure +: +false +waypoint_task_executor_plugin +: +"wait_at_waypoint" +wait_at_waypoint +: +plugin +: +"nav2_waypoint_follower::WaitAtWaypoint" +enabled +: +True +waypoint_pause_duration +: +0 +``` diff --git "a/exported_docs/nav2/WouldAControllerRecoveryHelp\357\203\201.txt" "b/exported_docs/nav2/WouldAControllerRecoveryHelp\357\203\201.txt" new file mode 100644 index 0000000..5f8874d --- /dev/null +++ "b/exported_docs/nav2/WouldAControllerRecoveryHelp\357\203\201.txt" @@ -0,0 +1,22 @@ +Title: WouldAControllerRecoveryHelp +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldAControllerRecoveryHelp.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Port + + +## Example + + +Code Examples: + +Language: unknown +File: FAILURE +``` + +``` diff --git "a/exported_docs/nav2/WouldAPlannerRecoveryHelp\357\203\201.txt" "b/exported_docs/nav2/WouldAPlannerRecoveryHelp\357\203\201.txt" new file mode 100644 index 0000000..ad8fb6f --- /dev/null +++ "b/exported_docs/nav2/WouldAPlannerRecoveryHelp\357\203\201.txt" @@ -0,0 +1,22 @@ +Title: WouldAPlannerRecoveryHelp +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldAPlannerRecoveryHelp.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Port + + +## Example + + +Code Examples: + +Language: unknown +File: FAILURE +``` + +``` diff --git "a/exported_docs/nav2/WouldASmootherRecoveryHelp\357\203\201.txt" "b/exported_docs/nav2/WouldASmootherRecoveryHelp\357\203\201.txt" new file mode 100644 index 0000000..ce62294 --- /dev/null +++ "b/exported_docs/nav2/WouldASmootherRecoveryHelp\357\203\201.txt" @@ -0,0 +1,22 @@ +Title: WouldASmootherRecoveryHelp +URL: https://docs.nav2.org/configuration/packages/bt-plugins/conditions/WouldASmootherRecoveryHelp.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Input Port + + +## Example + + +Code Examples: + +Language: unknown +File: FAILURE +``` + +``` diff --git "a/exported_docs/nav2/Writing a New Behavior Plugin\357\203\201.txt" "b/exported_docs/nav2/Writing a New Behavior Plugin\357\203\201.txt" new file mode 100644 index 0000000..611b944 --- /dev/null +++ "b/exported_docs/nav2/Writing a New Behavior Plugin\357\203\201.txt" @@ -0,0 +1,461 @@ +Title: Writing a New Behavior Plugin +URL: https://docs.nav2.org/plugin_tutorials/docs/writing_new_behavior_plugin.html#exporting-the-behavior-plugin +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to create you own Behavior Plugin. +The Behavior Plugins live in the behavior server. +Unlike the planner and controller servers, each behavior will host its own unique action server. +The planners and controllers have the same API as they accomplish the same task. +However, recoveries can be used to do a wide variety of tasks, so each behavior can have its own unique action message definition and server. +This allows for massive flexibility in the behavior server enabling any behavior action imaginable that doesn’t need to have other reuse. + +## Requirements + + +## Tutorial Steps + + +## 1- Creating a new Behavior Plugin +We will create a simple send sms behavior. +It will use Twilio to send a message via SMS to a remote operations center. +The code in this tutorial can be found innavigation_tutorialsrepository asnav2_sms_behavior. +This package can be a considered as a reference for writing Behavior Plugin. +Our example plugin implements the plugin class ofnav2_core::Behavior. +However, we have a nice wrapper for actions innav2_behaviors, so we use thenav2_behaviors::TimedBehaviorbase class for this application instead. +This wrapper class derives from thenav2_coreclass so it can be used as a plugin, but handles the vast majority of ROS 2 action server boiler plate required. +The base class fromnav2_coreprovides 4 pure virtual methods to implement a Behavior Plugin. +The plugin will be used by the behavior server to host the plugins, but each plugin will provide their own unique action server interface. +Let’s learn more about the methods needed to write a Behavior Pluginif you did not use the ``nav2_behaviors`` wrapper. +For thenav2_behaviorswrapper, which provides the ROS 2 action interface and boilerplate, we have 4 virtual methods to implement. +This tutorial uses this wrapper so these are the main elements we will address. +For this tutorial, we will be using methodsonRun(),onCycleUpdate(), andonConfigure()to create the SMS behavior.onConfigure()will be skipped for brevity, but only declares parameters. +In recoveries,onRun()method must set any initial state and kick off the behavior. +For the case of our call for help behavior, we can trivially compute all of our needs in this method. +We receive an action goal,command, which we want to process.commandcontains a fieldmessagethat contains the message we want to communicate to our mothership. +This is the “call for help” message that we want to send via SMS to our brothers in arms in the operations center. +We use the service Twilio to complete this task. +Pleasecreate an accountand get all the relevant information needed for creating the service (e.g.account_sid,auth_token, and a phone number). +You can set these values as parameters in your configuration files corresponding to theonConfigure()parameter declarations. +We use the_twilioobject to send our message with your account information from the configuration file. +We send the message and log to screen whether or not the message was sent successfully or not. +We return aFAILEDorSUCCEEDEDdepending on this value to be returned to the action client. +onCycleUpdate()is trivially simple as a result of our short-running behavior. +If the behavior was instead longer running like spinning, navigating to a safe area, or getting out of a bad spot and waiting for help, then this function would be checking for timeouts or computing control values. +For our example, we simply return success because we already completed our mission inonRun(). +The remaining methods are not used and are not mandatory to override them. + +## 2- Exporting the Behavior Plugin +Now that we have created our custom behavior, we need to export our Behavior Plugin so that it would be visible to the behavior server. Plugins are loaded at runtime and if they are not visible, then our behavior server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib. +Coming to our tutorial, classnav2_sms_bahavior::SendSmsis loaded dynamically asnav2_core::Behaviorwhich is our base class. +Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting. +It is good practice to place these lines at the end of the file but technically, you can also write at the top. + +## 3- Pass the plugin name through params file +To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params +with +In the above snippet, you can observe that we add the SMS behavior under thesend_smsROS 2 action server name. +We also tell the behavior server that thesend_smsis of typeSendSmsand give it our parameters for your Twilio account. + +## 4- Run Behavior Plugin +Run Turtlebot3 simulation with enabled Nav2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that: +In a new terminal run: + +Code Examples: + +Language: unknown +File: onRun() +``` +Status +SendSms::onRun +( +const +std +:: +shared_ptr +< +const +Action +:: +Goal +> +command +) +{ +std +:: +string +response +; +bool +message_success += +_twilio +-> +send_message +( +_to_number +, +_from_number +, +command +-> +message +, +response +, +"" +, +false +); +if +( +! +message_success +) +{ +RCLCPP_INFO +( +node_ +-> +get_logger +(), +"SMS send failed." +); +return +ResultStatus +{ +Status +:: +FAILED +}; +} +RCLCPP_INFO +( +node_ +-> +get_logger +(), +"SMS sent successfully!" +); +return +ResultStatus +{ +Status +:: +SUCCEEDED +}; +} +``` + +Language: unknown +File: onRun() +``` +Status +SendSms::onCycleUpdate +() +{ +return +Status +:: +SUCCEEDED +; +} +``` + +Language: unknown +File: nav2_core::Behavior +``` +#include +"pluginlib/class_list_macros.hpp" +PLUGINLIB_EXPORT_CLASS +( +nav2_sms_bahavior +:: +SendSms +, +nav2_core +:: +Behavior +) +``` + +Language: unknown +File: description +``` + + + +This +is +an +example +plugin +which +produces +an +SMS +text +message +recovery. + + + +``` + +Language: unknown +File: share +``` +pluginlib_export_plugin_description_file(nav2_core behavior_plugin.xml) + +``` + +Language: unknown +File: package.xml +``` + + +ament_cmake + + + +``` + +Language: unknown +File: nav2_params.yaml +``` +behavior_server +: +# Humble and later +recoveries_server +: +# Galactic and earlier +ros__parameters +: +costmap_topic +: +local_costmap/costmap_raw +footprint_topic +: +local_costmap/published_footprint +cycle_frequency +: +10.0 +behavior_plugins +: +[ +"spin" +, +"backup" +, +"wait" +] +# Humble and later +recovery_plugins +: +[ +"spin" +, +"backup" +, +"wait" +] +# Galactic and earlier +spin +: +plugin +: +"nav2_behaviors::Spin" +# In Iron and older versions, "/" was used instead of "::" +backup +: +plugin +: +"nav2_behaviors::BackUp" +# In Iron and older versions, "/" was used instead of "::" +wait +: +plugin +: +"nav2_behaviors::Wait" +# In Iron and older versions, "/" was used instead of "::" +global_frame +: +odom +robot_base_frame +: +base_link +transform_timeout +: +0.1 +use_sim_time +: +true +simulate_ahead_time +: +2.0 +max_rotational_vel +: +1.0 +min_rotational_vel +: +0.4 +rotational_acc_lim +: +3.2 +``` + +Language: unknown +File: nav2_params.yaml +``` +behavior_server +: +# Humble and newer +recoveries_server +: +# Galactic and earlier +ros__parameters +: +local_costmap_topic +: +local_costmap/costmap_raw +local_footprint_topic +: +local_costmap/published_footprint +global_costmap_topic +: +global_costmap/costmap_raw +global_footprint_topic +: +global_costmap/published_footprint +cycle_frequency +: +10.0 +behavior_plugins +: +[ +"spin" +, +"backup" +, +"wait" +, +"send_sms" +] +# Humble and newer +recovery_plugins +: +[ +"spin" +, +"backup" +, +"wait" +, +"send_sms" +] +# Galactic and earlier +spin +: +plugin +: +"nav2_behaviors::Spin" +# In Iron and older versions, "/" was used instead of "::" +backup +: +plugin +: +"nav2_behaviors::BackUp" +# In Iron and older versions, "/" was used instead of "::" +wait +: +plugin +: +"nav2_behaviors::Wait" +# In Iron and older versions, "/" was used instead of "::" +send_sms +: +plugin +: +"nav2_sms_behavior::SendSms" +# In Iron and older versions, "/" was used instead of "::" +account_sid +: +... +# your sid +auth_token +: +... +# your token +from_number +: +... +# your number +to_number +: +... +# the operations center number +global_frame +: +odom +robot_base_frame +: +base_link +transform_timeout +: +0.1 +use_sim_time +: +true +simulate_ahead_time +: +2.0 +max_rotational_vel +: +1.0 +min_rotational_vel +: +0.4 +rotational_acc_lim +: +3.2 +``` + +Language: unknown +File: SendSms +``` +$ +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +params_file: += +/path/to/your_params_file.yaml + +``` + +Language: unknown +File: SendSms +``` +$ +ros2 +action +send_goal +"send_sms" +nav2_sms_behavior/action/SendSms +"{message : Hello!! Navigation2 World }" +``` diff --git "a/exported_docs/nav2/Writing a New Behavior Tree Plugin\357\203\201.txt" "b/exported_docs/nav2/Writing a New Behavior Tree Plugin\357\203\201.txt" new file mode 100644 index 0000000..b991e77 --- /dev/null +++ "b/exported_docs/nav2/Writing a New Behavior Tree Plugin\357\203\201.txt" @@ -0,0 +1,396 @@ +Title: Writing a New Behavior Tree Plugin +URL: https://docs.nav2.org/plugin_tutorials/docs/writing_new_bt_plugin.html#creating-a-new-bt-plugin +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to create your own behavior tree (BT) plugin. +The BT plugins are used as nodes in the behavior tree XML processed by the BT Navigator for navigation logic. + +## Requirements + + +## Tutorial Steps + + +## 1- Creating a new BT Plugin +We will create a simple BT plugin node to perform an action on another server. +For this example, we’re going to analyze the simplest behavior tree action node in thenav2_behavior_treepackage, thewaitnode. +Beyond this example of an action BT node, you can also create custom decorator, condition, and control nodes. +Each node type has a unique role in the behavior tree to perform actions like planning, control the flow of the BT, check the status of a condition, or modify the output of other BT nodes. +The code in this tutorial can be found innav2_behavior_treepackage as thewait_actionnode. +This action node can be considered as a reference for writing other action node plugins. +Our example plugin inherits from the base classnav2_behavior_tree::BtActionNode. +The base class is a wrapper on the BehaviorTree.CPPBT::ActionNodeBasethat simplifies BT action nodes that utilize ROS 2 action clients. +AnBTActionNodeis both a BT action and uses ROS 2 action network interfaces for calling a remote server to do some work. +When working with other types of BT nodes (e.g. decorator, control, condition) use the corresponding BT node,BT::DecoratorNode,BT::ControlNode, orBT::ConditionNode. +For BT action nodes that donotutilize ROS 2 action interfaces, use theBT::ActionNodeBasebase class itself. +TheBTActionNodeclass provides 5 virtual methods to use, in addition to the information provided in the constructor. +Let’s learn more about the methods needed to write a BT action plugin. +For this tutorial, we will only be using theon_tick()method. +In the constructor, we need to get any non-variable parameters that apply to the behavior tree node. +In this example, we need to get the value of the duration to sleep from the input port of the behavior tree XML. +Here, we give the input of thexml_tag_name, which tells the BT node plugin the string in the XML that corresponds to this node. +This will be seen later when we register this BT node as a plugin. +It also takes in the string name of the action server that it will call to execute some behavior. +Finally, a set of configurations that we can safely ignore for the purposes of most node plugins. +We then call theBTActionNodeconstructor. As can be seen, it’s templated by the ROS 2 action type, so we give it thenav2_msgs::action::Waitaction message type and forward our other inputs. +TheBTActionNodehas thetick()method, which is called directly by the behavior tree when this node is called from the tree.on_tick()is then called before sending the action client goal. +In the body of the constructor, we get the input portgetInputof the parameterwait_duration, which can be configured independently for every instance of thewaitnode in the tree. +It is set in thedurationparameter and inserted into thegoal_. +Thegoal_class variable is the goal that the ROS 2 action client will send to the action server. +So in this example, we set the duration to the time we want to wait by so that the action server knows the specifics of our request. +TheprovidedPorts()method gives us the opportunity to define input or output ports. +Ports can be thought of as parameters that the behavior tree node has access to from the behavior tree itself. +For our example, there is only a single input port, thewait_durationwhich can be set in the BT XML for each instance of thewaitrecovery. +We set the type,int, the default1, the namewait_duration, and a description of the portWaittime. +Theon_tick()method is called when the behavior tree ticks a specific node. +For the wait BT node, we simply want to notify a counter on the blackboard that an action plugin that corresponds to a recovery was ticked. +This is useful to keep metrics about the number of recoveries executed during a specific navigation run. +You could also log or update thegoal_waiting duration if that is a variable input. +The remaining methods are not used and are not mandatory to override them. +Only some BT node plugins will require overridingon_wait_for_result()to check for preemption or check a timeout. +The success, aborted, and cancelled methods will default toSUCCESS,FAILURE,SUCCESSrespectively, if not overridden. + +## 2- Exporting the planner plugin +Now that we have created our custom BT node, we need to export our plugin so that it would be visible to the behavior tree when it loads a custom BT XML. +Plugins are loaded at runtime, and if they are not visible, then our BT Navigator server won’t be able to load them or use them. +In BehaviorTree.CPP, exporting and loading plugins is handled by theBT_REGISTER_NODESmacro. +In this macro, we must create aNodeBuilderso that our custom action node can have a non-default constructor signature (for the action and xml names). +This lambda will return a unique pointer to the behavior tree node we have created. +Fill in the constructor with the relevant information, giving it thenameandconfiggiven in the function arguments. +Then define the ROS 2 action server’s name that this BT node will call, in this case, it’s theWaitaction. +We finally give the builder to a factory to register.Waitgiven to the factory is the name in the behavior tree XML file that corresponds to this BT node plugin. +An example can be seen below, where theWaitBT XML node specifies a non-variable input portwait_durationof 5 seconds. + +## 3- Add plugin library name to config +In order for the BT Navigator node to discover the plugin we’ve just registered, we need to list the plugin library name under the bt_navigator node in the configuration YAML file. Configuration should look similar to the one shown below. Take note of nav2_wait_action_bt_node listed under plugin_lib_names. + +## 4- Run Your Custom plugin +Now you can use a behavior tree with your custom BT node. +For example, thenavigate_w_replanning_and_recovery.xmlfile is shown below. +Select this BT XML file in your specific navigation request inNavigateToPoseor as the default behavior tree in the BT Navigator’s configuration yaml file. + +Code Examples: + +Language: unknown +File: on_tick() +``` +WaitAction +:: +WaitAction +( +const +std +:: +string +& +xml_tag_name +, +const +std +:: +string +& +action_name +, +const +BT +:: +NodeConfiguration +& +conf +) +: +BtActionNode +< +nav2_msgs +:: +action +:: +Wait +> +( +xml_tag_name +, +action_name +, +conf +) +{ +int +duration +; +getInput +( +"wait_duration" +, +duration +); +if +( +duration +<= +0 +) +{ +RCLCPP_WARN +( +node_ +-> +get_logger +(), +"Wait duration is negative or zero " +"(%i). Setting to positive." +, +duration +); +duration +*= +-1 +; +} +goal_ +. +time +. +sec += +duration +; +} +``` + +Language: unknown +File: Waittime +``` +static +BT +:: +PortsList +providedPorts +() +{ +return +providedBasicPorts +( +{ +BT +:: +InputPort +< +int +> +( +"wait_duration" +, +1 +, +"Wait time" +) +}); +} +``` + +Language: unknown +File: goal_ +``` +void +WaitAction::on_tick +() +{ +increment_recovery_count +(); +} +``` + +Language: unknown +File: BT_REGISTER_NODES +``` +BT_REGISTER_NODES +( +factory +) +{ +BT +:: +NodeBuilder +builder += +[]( +const +std +:: +string +& +name +, +const +BT +:: +NodeConfiguration +& +config +) +{ +return +std +:: +make_unique +< +nav2_behavior_tree +:: +WaitAction +> +( +name +, +"wait" +, +config +); +}; +factory +. +registerBuilder +< +nav2_behavior_tree +:: +WaitAction +> +( +"Wait" +, +builder +); +} +``` + +Language: unknown +File: wait_duration +``` + +``` + +Language: unknown +File: wait_duration +``` +bt_navigator: + ros__parameters: + use_sim_time: True + global_frame: map + robot_base_frame: base_link + odom_topic: /odom + default_bt_xml_filename: "navigate_w_replanning_and_recovery.xml" + plugin_lib_names: + - nav2_back_up_action_bt_node # other plugin + - nav2_wait_action_bt_node # our new plugin + +``` + +Language: unknown +File: NavigateToPose +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git "a/exported_docs/nav2/Writing a New Controller Plugin\357\203\201.txt" "b/exported_docs/nav2/Writing a New Controller Plugin\357\203\201.txt" new file mode 100644 index 0000000..3267811 --- /dev/null +++ "b/exported_docs/nav2/Writing a New Controller Plugin\357\203\201.txt" @@ -0,0 +1,606 @@ +Title: Writing a New Controller Plugin +URL: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2controller_plugin.html#writing-new-nav2controller-plugin +Section: tuning/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to create your own controllerplugin. +In this tutorial, we will be implementing the pure pursuit path tracking algorithm based on thispaper. +It is recommended you go through it. +Note: This tutorial is based on a previously existing simplified version of the Regulated Pure Pursuit controller now in the Nav2 stack. +You can find the source code matching this tutorialhere. + +## Requirements + + +## Tutorial Steps + + +## 1- Create a new Controller Plugin +We will be implementing the pure pursuit controller. The annotated code in this tutorial can be found innavigation_tutorialsrepository +as thenav2_pure_pursuit_controller. This package can be considered as a reference for writing your own controller plugin. +Our example plugin classnav2_pure_pursuit_controller::PurePursuitControllerinherits from the base classnav2_core::Controller. The base class provides a +set of virtual methods to implement a controller plugin. These methods are called at runtime by the controller server to compute velocity commands. +The list of methods, their descriptions, and necessity are presented in the table below: +In this tutorial, we will use the methodsPurePursuitController::configure,PurePursuitController::setPlanandPurePursuitController::computeVelocityCommands. +In controllers,configure()method must set member variables from ROS parameters and perform any initialization required. +Here,plugin_name_+".desired_linear_vel"is fetching the ROS parameterdesired_linear_velwhich is specific to our controller. +Nav2 allows loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. +Now, if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. +For example, our example controller is mapped to the nameFollowPathand to retrieve thedesired_linear_velparameter, which is specific to “FollowPath”, +we usedFollowPath.desired_linear_vel. In other words,FollowPathis used as a namespace for plugin-specific parameters. +We will see more on this when we discuss the parameters file (or params file). +The passed-in arguments are stored in member variables so that they can be used at a later stage if needed. +InsetPlan()method, we receive the updated global path for the robot to follow. In our example, we transform the received global path into +the frame of the robot and then store this transformed global path for later use. +The computation for the desired velocity happens in thecomputeVelocityCommands()method. It is used to calculate the desired velocity command given the current velocity and pose. +The third argument - is a pointer to thenav2_core::GoalChecker, that checks whether a goal has been reached. In our example, this won’t be used. +In the case of pure pursuit, the algorithm computes velocity commands such that the robot tries to follow the global path as closely as possible. +This algorithm assumes a constant linear velocity and computes the angular velocity based on the curvature of the global path. +The remaining methods are not used, but it’s mandatory to override them. As per the rules, we did override all but left them empty. + +## 2- Exporting the controller plugin +Now that we have created our custom controller, we need to export our controller plugin so that it will be visible to the controller server. +Plugins are loaded at runtime, and if they are not visible, then our controller server won’t be able to load them. In ROS 2, exporting and loading +plugins is handled bypluginlib. +Coming back to our tutorial, classnav2_pure_pursuit_controller::PurePursuitControlleris loaded dynamically asnav2_core::Controllerwhich is our base class. +Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting. +It is good practice to place these lines at the end of the file, but technically, you can also write at the top. + +## 3- Pass the plugin name through the params file +To enable the plugin, we need to modify thenav2_params.yamlfile as below +In the above snippet, you can observe the mapping of ournav2_pure_pursuit_controller::PurePursuitControllercontroller to its idFollowPath. +To pass plugin-specific parameters we have used.. + +## 4- Run Pure Pursuit Controller plugin +Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that: +Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started. +The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to. +After that controller will make the robot follow the global path. + +Code Examples: + +Language: unknown +File: configure() +``` +void +PurePursuitController::configure +( +const +rclcpp_lifecycle +:: +LifecycleNode +:: +WeakPtr +& +parent +, +std +:: +string +name +, +std +:: +shared_ptr +< +tf2_ros +:: +Buffer +> +tf +, +std +:: +shared_ptr +< +nav2_costmap_2d +:: +Costmap2DROS +> +costmap_ros +) +{ +node_ += +parent +; +auto +node += +node_ +. +lock +(); +costmap_ros_ += +costmap_ros +; +tf_ += +tf +; +plugin_name_ += +name +; +logger_ += +node +-> +get_logger +(); +clock_ += +node +-> +get_clock +(); +declare_parameter_if_not_declared +( +node +, +plugin_name_ ++ +".desired_linear_vel" +, +rclcpp +:: +ParameterValue +( +0.2 +)); +declare_parameter_if_not_declared +( +node +, +plugin_name_ ++ +".lookahead_dist" +, +rclcpp +:: +ParameterValue +( +0.4 +)); +declare_parameter_if_not_declared +( +node +, +plugin_name_ ++ +".max_angular_vel" +, +rclcpp +:: +ParameterValue +( +1.0 +)); +declare_parameter_if_not_declared +( +node +, +plugin_name_ ++ +".transform_tolerance" +, +rclcpp +:: +ParameterValue +( +0.1 +)); +node +-> +get_parameter +( +plugin_name_ ++ +".desired_linear_vel" +, +desired_linear_vel_ +); +node +-> +get_parameter +( +plugin_name_ ++ +".lookahead_dist" +, +lookahead_dist_ +); +node +-> +get_parameter +( +plugin_name_ ++ +".max_angular_vel" +, +max_angular_vel_ +); +double +transform_tolerance +; +node +-> +get_parameter +( +plugin_name_ ++ +".transform_tolerance" +, +transform_tolerance +); +transform_tolerance_ += +rclcpp +:: +Duration +:: +from_seconds +( +transform_tolerance +); +} +``` + +Language: unknown +File: setPlan() +``` +void +PurePursuitController::setPlan +( +const +nav_msgs +:: +msg +:: +Path +& +path +) +{ +// Transform global path into the robot's frame +global_plan_ += +transformGlobalPlan +( +path +); +} +``` + +Language: unknown +File: nav2_core::GoalChecker +``` +geometry_msgs +:: +msg +:: +TwistStamped +PurePursuitController::computeVelocityCommands +( +const +geometry_msgs +:: +msg +:: +PoseStamped +& +pose +, +const +geometry_msgs +:: +msg +:: +Twist +& +velocity +, +nav2_core +:: +GoalChecker +* +/*goal_checker*/ +) +{ +// Find the first pose which is at a distance greater than the specified lookahead distance +auto +goal_pose += +std +:: +find_if +( +global_plan_ +. +poses +. +begin +(), +global_plan_ +. +poses +. +end +(), +[ +& +]( +const +auto +& +global_plan_pose +) +{ +return +hypot +( +global_plan_pose +. +pose +. +position +. +x +, +global_plan_pose +. +pose +. +position +. +y +) +>= +lookahead_dist_ +; +}) +-> +pose +; +double +linear_vel +, +angular_vel +; +// If the goal pose is in front of the robot then compute the velocity using the pure pursuit algorithm +// else rotate with the max angular velocity until the goal pose is in front of the robot +if +( +goal_pose +. +position +. +x +> +0 +) +{ +auto +curvature += +2.0 +* +goal_pose +. +position +. +y +/ +( +goal_pose +. +position +. +x +* +goal_pose +. +position +. +x ++ +goal_pose +. +position +. +y +* +goal_pose +. +position +. +y +); +linear_vel += +desired_linear_vel_ +; +angular_vel += +desired_linear_vel_ +* +curvature +; +} +else +{ +linear_vel += +0.0 +; +angular_vel += +max_angular_vel_ +; +} +// Create and publish a TwistStamped message with the desired velocity +geometry_msgs +:: +msg +:: +TwistStamped +cmd_vel +; +cmd_vel +. +header +. +frame_id += +pose +. +header +. +frame_id +; +cmd_vel +. +header +. +stamp += +clock_ +-> +now +(); +cmd_vel +. +twist +. +linear +. +x += +linear_vel +; +cmd_vel +. +twist +. +angular +. +z += +max +( +-1.0 +* +abs +( +max_angular_vel_ +), +min +( +angular_vel +, +abs +( +max_angular_vel_ +))); +return +cmd_vel +; +} +``` + +Language: unknown +File: nav2_core::Controller +``` +#include +"pluginlib/class_list_macros.hpp" +PLUGINLIB_EXPORT_CLASS +( +nav2_pure_pursuit_controller +:: +PurePursuitController +, +nav2_core +:: +Controller +) +``` + +Language: unknown +File: description +``` + + + +This +is +pure +pursuit +controller + + + + +``` + +Language: unknown +File: share +``` +pluginlib_export_plugin_description_file(nav2_core pure_pursuit_controller_plugin.xml) + +``` + +Language: unknown +File: package.xml +``` + + +ament_cmake + + + +``` + +Language: unknown +File: nav2_params.yaml +``` +controller_server: + ros__parameters: + controller_plugins: ["FollowPath"] + + FollowPath: + plugin: "nav2_pure_pursuit_controller::PurePursuitController" # In Iron and older versions, "/" was used instead of "::" + debug_trajectory_details: True + desired_linear_vel: 0.2 + lookahead_dist: 0.4 + max_angular_vel: 1.0 + transform_tolerance: 1.0 + +``` + +Language: unknown +File: . +``` +$ +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +params_file: += +/path/to/your_params_file.yaml + +``` diff --git "a/exported_docs/nav2/Writing a New Costmap2D Plugin\357\203\201.txt" "b/exported_docs/nav2/Writing a New Costmap2D Plugin\357\203\201.txt" new file mode 100644 index 0000000..93b48fb --- /dev/null +++ "b/exported_docs/nav2/Writing a New Costmap2D Plugin\357\203\201.txt" @@ -0,0 +1,321 @@ +Title: Writing a New Costmap2D Plugin +URL: https://docs.nav2.org/plugin_tutorials/docs/writing_new_costmap2d_plugin.html#overview +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to create your own simplepluginfor Costmap2D. +Before starting the tutorial, please check thisvideowhich contains information about Costmap2D layers design and plugins basic operational principals. + +## Requirements +It is assumed that ROS 2, Gazebo and TurtleBot3 packages are installed or built locally. Please make sure that Nav2 project is also built locally as it was made inBuild and Install. + +## Tutorial Steps + + +## 1- Write a new Costmap2D plugin +For a demonstration, this example will create a costmap plugin that puts repeating cost gradients in the costmap. +The annotated code for this tutorial can be found innavigation2_tutorialsrepository as thenav2_gradient_costmap_pluginROS 2-package. +Please refer to it when making your own layer plugin for Costmap2D. +The plugin classnav2_gradient_costmap_plugin::GradientLayeris inherited from basic classnav2_costmap_2d::Layer: +The basic class provides the set of virtual methods API for working with costmap layers in a plugin. These methods are called at runtime byLayeredCostmap. The list of methods, their description, and necessity to have these methods in plugin’s code is presented in the table below: +In our example these methods have the following functionality: +and setsneed_recalculation_bounds recalculation indicator: +where theGRADIENT_SIZEis the size of each gradient period in map cells,GRADIENT_FACTOR- decrement of costmap’s value per each step: +These parameters are defined in plugin’s header file. + +## 2- Export and make GradientLayer plugin +The written plugin will be loaded at runtime as its basic parent class and then will be called by plugin handling modules (for costmap2d byLayeredCostmap). Pluginlib opens a given plugin in run-time and provides methods from exported classes to be callable. The mechanism of class exporting tells pluginlib which basic class should be used during these calls. This allows to extend an application by plugins without knowing application source code or recompiling it. +In our example thenav2_gradient_costmap_plugin::GradientLayerplugin’s class should be dynamically loaded as anav2_costmap_2d::Layerbasic class. For this the plugin should be registered as follows: +This part is usually placed at the end of cpp-file where the plugin class was written (in our examplegradient_layer.cpp). It is good practice to place these lines at the end of the file, but technically, you can also place at the top. +The export of plugin is performed by includingpluginlib_export_plugin_description_file()cmake-function intoCMakeLists.txt. This function installs plugin description file intosharedirectory and sets ament indexes for plugin description XML to be discoverable as a plugin of selected type: +Plugin description file is also should be added topackage.xml.costmap_2dis the package of the interface definition, for our caseLayer, and requires a path to the xml file: +After everything is done put the plugin package intosrcdirectory of a certain ROS 2-workspace, build the plugin package (colconbuild--packages-selectnav2_gradient_costmap_plugin--symlink-install) and sourcesetup.bashfile when it necessary. +Now the plugin is ready to use. + +## 3- Enable the plugin in Costmap2D +At the next step it is required to tell Costmap2D about new plugin. For that the plugin should be added toplugin_namesandplugin_typeslists innav2_params.yamloptionally forlocal_costmap/global_costmapin order to be enabled in run-time for Controller/Planner Server.plugin_nameslist contains the names of plugin objects. These names could be anything you want.plugin_typescontains types of listed inplugin_namesobjects. These types should correspond tonamefield of plugin class specified in plugin description XML-file. +For example: +YAML-file may also contain the list of parameters (if any) for each plugin, identified by plugins object name. +NOTE: there could be many simultaneously loaded plugin objects of one type. For this,plugin_nameslist should contain different plugins names whether theplugin_typeswill remain the same types. For example: +In this case each plugin object will be handled by its own parameters tree in a YAML-file, like: + +## 4- Run GradientLayer plugin +Run Turtlebot3 simulation with enabled Nav2. Detailed instructions how to make it are written atGetting Started. Below is shortcut command for that: +Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on map as it was described inGetting Started. Robot will be localized on map and the result should be as presented at picture below. There, the gradient costmap can be seen. There are also 2 noticeable things: dynamically updated byGradientLayer::updateCosts()costmap within its bounds and global path curved by gradient: + +Code Examples: + +Language: unknown +File: nav2_costmap_2d::Layer +``` +namespace +nav2_gradient_costmap_plugin +{ +class +GradientLayer +: +public +nav2_costmap_2d +:: +Layer +``` + +Language: unknown +File: GradientLayer::onInitialize() +``` +declareParameter +( +"enabled" +, +rclcpp +:: +ParameterValue +( +true +)); +node_ +-> +get_parameter +( +name_ ++ +"." ++ +"enabled" +, +enabled_ +); +``` + +Language: unknown +File: need_recalculation_ +``` +need_recalculation_ += +false +; +``` + +Language: unknown +File: updateWithTrueOverwrite() +``` +int +gradient_index +; +for +( +int +j += +min_j +; +j +< +max_j +; +j +++ +) +{ +// Reset gradient_index each time when reaching the end of re-calculated window +// by OY axis. +gradient_index += +0 +; +for +( +int +i += +min_i +; +i +< +max_i +; +i +++ +) +{ +int +index += +master_grid +. +getIndex +( +i +, +j +); +// setting the gradient cost +unsigned +char +cost += +( +LETHAL_OBSTACLE +- +gradient_index +* +GRADIENT_FACTOR +) +% +255 +; +if +( +gradient_index +<= +GRADIENT_SIZE +) +{ +gradient_index +++ +; +} +else +{ +gradient_index += +0 +; +} +master_array +[ +index +] += +cost +; +} +} +``` + +Language: unknown +File: PLUGINLIB_EXPORT_CLASS +``` +#include "pluginlib/class_list_macros.hpp" +PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, nav2_costmap_2d::Layer) + +``` + +Language: unknown +File: description +``` + + + +This +is +an +example +plugin +which +puts +repeating +costs +gradients +to +costmap + + + +``` + +Language: unknown +File: share +``` +pluginlib_export_plugin_description_file(nav2_costmap_2d gradient_layer.xml) + +``` + +Language: unknown +File: Layer +``` + + + ... + + +``` + +Language: unknown +File: plugin:MyPlugin::Plugin +``` +--- a/nav2_bringup/bringup/params/nav2_params.yaml ++++ b/nav2_bringup/bringup/params/nav2_params.yaml +@@ -124,8 +124,8 @@ local_costmap: + width: 3 + + height: 3 + + resolution: 0.05 + +- plugins: ["obstacle_layer", "voxel_layer", "inflation_layer"] ++ plugins: ["obstacle_layer", "voxel_layer", "gradient_layer"] + robot_radius: 0.22 + + inflation_layer: + + cost_scaling_factor: 3.0 + +@@ -171,8 +171,8 @@ global_costmap: + robot_base_frame: base_link + + global_frame: map + + use_sim_time: True + +- plugins: ["static_layer", "obstacle_layer", "voxel_layer", "inflation_layer"] ++ plugins: ["static_layer", "obstacle_layer", "voxel_layer", "gradient_layer"] + robot_radius: 0.22 + + resolution: 0.05 + + obstacle_layer: + +``` + +Language: unknown +File: plugin_types +``` +plugins: ["obstacle_layer", "gradient_layer_1", "gradient_layer_2"] + +``` + +Language: unknown +File: plugin_types +``` +gradient_layer_1: + plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and older versions, "/" was used instead of "::" + enabled: True + ... +gradient_layer_2: + plugin: nav2_gradient_costmap_plugin::GradientLayer # In Iron and older versions, "/" was used instead of "::" + enabled: False + ... + +``` + +Language: unknown +File: plugin_types +``` +$ +ros2 +launch +nav2_bringup +tb3_simulation_launch.py + +``` diff --git "a/exported_docs/nav2/Writing a New Navigator Plugin\357\203\201.txt" "b/exported_docs/nav2/Writing a New Navigator Plugin\357\203\201.txt" new file mode 100644 index 0000000..aa5138d --- /dev/null +++ "b/exported_docs/nav2/Writing a New Navigator Plugin\357\203\201.txt" @@ -0,0 +1,781 @@ +Title: Writing a New Navigator Plugin +URL: https://docs.nav2.org/plugin_tutorials/docs/writing_new_navigator_plugin.html#create-a-new-navigator-plugin +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to create your own behavior-tree navigatorpluginbased on thenav2_core::BehaviorTreeNavigatorbase class. +In this tutorial, we will be reviewing theNavigatetoPosebehavior-tree navigator plugin, which is the foundational navigator of Nav2 and complimentary behavior to ROS 1 Navigation. This completes point-to-point navigation. This tutorial will be reviewing the code and structure as of ROS 2 Iron. While small variations may be made over time, this should be sufficient to get started writing your own navigator if you choose as we do not expect major API changes on this system. +It may be beneficial to write your own Navigator if you have a custom action message definition you’d like to use with Navigation rather than the providedNavigateToPoseorNavigateThroughPosesinterfaces (e.g. doing complete coverage or containing additional constraint information). The role of the Navigators are to extract information from requests to pass to the behavior tree / blackboard, populate feedback and responses, and maintain the state of the behavior tree if relevant. The behavior tree XML will define the actual navigation logic used. + +## Requirements + + +## Tutorial Steps + + +## 1- Create a new Navigator Plugin +We will be implementing pure point-to-point navigation behavior. The code in this tutorial can be found inNav2’s BT Navigator packageas theNavigateToPoseNavigator. This package can be considered as a reference for writing your own plugin. +Our example plugin classnav2_bt_navigator::NavigateToPoseNavigatorinherits from the base classnav2_core::BehaviorTreeNavigator. The base class provides a set of virtual methods to implement a navigator plugin. These methods are called at runtime by the BT Navigator server or as a response to ROS 2 actions to process a navigation request. +Note that this class has itself a base class ofNavigatorBase. This class is to provide a non-templated base-class for use in loading the plugins into vectors for storage and calls for basic state transition in the lifecycle node. Its members (e.g.on_XYZ) are implemented for you inBehaviorTreeNavigatorand marked asfinalso they are not possible to be overridden by the user. The API that you will be implementing for your navigator are the virtual methods withinBehaviorTreeNavigator, notNavigatorBase. Theseon_XYZAPIs are implemented in necessary functions inBehaviorTreeNavigatorto handle boilerplate logic regarding the behavior tree and action server to minimize code duplication across the navigator implementations (e.g.on_configurewill create the action server, register callbacks, populate the blackboard with some necessary basic information, and then call a user-definedconfigurefunction for any additional user-specific needs). +The list of methods, their descriptions, and necessity are presented in the table below: +In the Navigate to Pose Navigator,configure()method must determine the blackboard parameter names where the goal and paths are being stored, as these are key values for processing feedback inonLoopand for the different behavior tree nodes to communicate this information between themselves. Additionally and uniquely to this navigator type, we also create a client to itself and a subscription to thegoal_posetopic such that requests from the default configurations of Rviz2 using theGoal Posetool will be processed. +The values of the blackboard IDs are stored alongside the odometry smoother the BT Navigator provides for populating meaningful feedback later. Complimentary to this, thecleanupmethod will reset these resources. The activate and deactivate methods are not used in this particular navigator. +In thegetDefaultBTFilepath(), we use a parameterdefault_nav_to_pose_bt_xmlto get the default behavior tree XML file to use if none is provided by the navigation request and to initialize the BT Navigator with a behavior tree hot-loaded. If one is not provided in the parameter files, then we grab a known and reasonable default XML file in thenav2_bt_navigatorpackage: +When a goal is received, we need to determine if this goal is valid and should be processed. +ThegoalReceivedmethod provides you thegoaland a return value if it is being processed or not. This information is sent back to the action server to notify the client. In this case, we want to make sure that the goal’s behavior tree is valid or else we cannot proceed. If it is valid, then we can initialize the goal pose onto the blackboard and reset some state in order to cleanly process this new request. +Once this goal is completed, we need to populate the Action’s result, if required and meaningful. In this navigator’s case, it contains no result information when the navigation request was completed successfully, so this method is empty. For other navigator types, you may populate theresultobject provided. +If however a goal is preempted (e.g. a new action request comes in while an existing request is being processed), theonPreempt()method is called to determine if the new request is genuine and appropriate to preempt the currently processing goal. For example, it might not be wise to accept a preeemption request if that request is fundamentally different in nature from an existing behavior tree task or when your existing task is of a higher priority. +Note that here you can also see theinitializeGoalPosemethod called. This method will set the goal parameters for this navigator onto the blackboard and reset important state information to cleanly reuse a behavior tree without old state information, as shown below: +The recovery counter and start time are both important feedback terms for a client to understand the state of the current task (e.g. if its failing, having problems, or taking exceptionally long). The setting of the goal on the blackboard is taken by theComputePathToPoseBT Action node to plan a new route to the goal (and then who’s path is communicated to theFollowPathBT node via the blackboard ID previously set). +The final function implemented isonLoop, which is simplified below for tutorial purposes. While anything can be done in this method, which is called as the BT is looping through the tree, it is common to use this as an opportunity to populate any necessary feedback about the state of the navigation request, robot, or metadata that a client might be interested in. + +## 2- Exporting the navigator plugin +Now that we have created our custom navigator, we need to export our plugin so that it would be visible to the BT Navigator server. +Plugins are loaded at runtime, and if they are not visible, then our server won’t be able to load it. In ROS 2, exporting and loading +plugins is handled bypluginlib. +Coming to our tutorial, classnav2_bt_navigator::NavigateToPoseNavigatoris loaded dynamically asnav2_core::NavigatorBasewhich is our base class due to the subtleties previously described. +Note that it requires pluginlib to export out the plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASS, which does all the work of exporting. +It is good practice to place these lines at the end of the file, but technically, you can also write at the top. + +## 3- Pass the plugin name through the params file +To enable the plugin, we need to modify thenav2_params.yamlfile as below +In the above snippet, you can observe the mapping of ournav2_bt_navigator::NavigateToPoseNavigatorplugin to its idnavigate_to_pose. +To pass plugin-specific parameters we have used.. + +## 4- Run plugin +Run Turtlebot3 simulation with enabled Nav2. Detailed instructions on how to make it run are written atGetting Started. Below is a shortcut command for that: +Then goto RViz and click on the “2D Pose Estimate” button at the top and point the location on the map as it was described inGetting Started. +The robot will localize on the map and then click on the “Nav2 goal” and click on the pose where you want your robot to navigate to. +After that navigator will take over with the behavior tree XML file behavior definition provided to it. + +Code Examples: + +Language: unknown +File: goal_pose +``` +bool +NavigateToPoseNavigator::configure +( +rclcpp_lifecycle +:: +LifecycleNode +:: +WeakPtr +parent_node +, +std +:: +shared_ptr +< +nav2_util +:: +OdomSmoother +> +odom_smoother +) +{ +start_time_ += +rclcpp +:: +Time +( +0 +); +auto +node += +parent_node +. +lock +(); +if +( +! +node +-> +has_parameter +( +"goal_blackboard_id" +)) +{ +node +-> +declare_parameter +( +"goal_blackboard_id" +, +std +:: +string +( +"goal" +)); +} +goal_blackboard_id_ += +node +-> +get_parameter +( +"goal_blackboard_id" +). +as_string +(); +if +( +! +node +-> +has_parameter +( +"path_blackboard_id" +)) +{ +node +-> +declare_parameter +( +"path_blackboard_id" +, +std +:: +string +( +"path" +)); +} +path_blackboard_id_ += +node +-> +get_parameter +( +"path_blackboard_id" +). +as_string +(); +// Odometry smoother object for getting current speed +odom_smoother_ += +odom_smoother +; +self_client_ += +rclcpp_action +:: +create_client +< +ActionT +> +( +node +, +getName +()); +goal_sub_ += +node +-> +create_subscription +< +geometry_msgs +:: +msg +:: +PoseStamped +> +( +"goal_pose" +, +rclcpp +:: +SystemDefaultsQoS +(), +std +:: +bind +( +& +NavigateToPoseNavigator +:: +onGoalPoseReceived +, +this +, +std +:: +placeholders +:: +_1 +)); +return +true +; +} +``` + +Language: unknown +File: cleanup +``` +bool +NavigateToPoseNavigator::cleanup +() +{ +goal_sub_ +. +reset +(); +self_client_ +. +reset +(); +return +true +; +} +``` + +Language: unknown +File: nav2_bt_navigator +``` +std +:: +string +NavigateToPoseNavigator::getDefaultBTFilepath +( +rclcpp_lifecycle +:: +LifecycleNode +:: +WeakPtr +parent_node +) +{ +std +:: +string +default_bt_xml_filename +; +auto +node += +parent_node +. +lock +(); +if +( +! +node +-> +has_parameter +( +"default_nav_to_pose_bt_xml" +)) +{ +std +:: +string +pkg_share_dir += +ament_index_cpp +:: +get_package_share_directory +( +"nav2_bt_navigator" +); +node +-> +declare_parameter +< +std +:: +string +> +( +"default_nav_to_pose_bt_xml" +, +pkg_share_dir ++ +"/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml" +); +} +node +-> +get_parameter +( +"default_nav_to_pose_bt_xml" +, +default_bt_xml_filename +); +return +default_bt_xml_filename +; +} +``` + +Language: unknown +File: goal +``` +bool +NavigateToPoseNavigator::goalReceived +( +ActionT +:: +Goal +:: +ConstSharedPtr +goal +) +{ +auto +bt_xml_filename += +goal +-> +behavior_tree +; +if +( +! +bt_action_server_ +-> +loadBehaviorTree +( +bt_xml_filename +)) +{ +RCLCPP_ERROR +( +logger_ +, +"BT file not found: %s. Navigation canceled." +, +bt_xml_filename +. +c_str +()); +return +false +; +} +initializeGoalPose +( +goal +); +return +true +; +} +``` + +Language: unknown +File: result +``` +void +NavigateToPoseNavigator::goalCompleted +( +typename +ActionT +:: +Result +:: +SharedPtr +/*result*/ +, +const +nav2_behavior_tree +:: +BtStatus +/*final_bt_status*/ +) +{ +} +``` + +Language: unknown +File: onPreempt() +``` +void +NavigateToPoseNavigator::onPreempt +( +ActionT +:: +Goal +:: +ConstSharedPtr +goal +) +{ +RCLCPP_INFO +( +logger_ +, +"Received goal preemption request" +); +if +( +goal +-> +behavior_tree +== +bt_action_server_ +-> +getCurrentBTFilename +() +|| +( +goal +-> +behavior_tree +. +empty +() +&& +bt_action_server_ +-> +getCurrentBTFilename +() +== +bt_action_server_ +-> +getDefaultBTFilename +())) +{ +// if pending goal requests the same BT as the current goal, accept the pending goal +// if pending goal has an empty behavior_tree field, it requests the default BT file +// accept the pending goal if the current goal is running the default BT file +initializeGoalPose +( +bt_action_server_ +-> +acceptPendingGoal +()); +} +else +{ +RCLCPP_WARN +( +logger_ +, +"Preemption request was rejected since the requested BT XML file is not the same " +"as the one that the current goal is executing. Preemption with a new BT is invalid " +"since it would require cancellation of the previous goal instead of true preemption." +" +\n +Cancel the current goal and send a new action request if you want to use a " +"different BT XML file. For now, continuing to track the last goal until completion." +); +bt_action_server_ +-> +terminatePendingGoal +(); +} +} +``` + +Language: unknown +File: initializeGoalPose +``` +void +NavigateToPoseNavigator::initializeGoalPose +( +ActionT +:: +Goal +:: +ConstSharedPtr +goal +) +{ +RCLCPP_INFO +( +logger_ +, +"Begin navigating from current location to (%.2f, %.2f)" +, +goal +-> +pose +. +pose +. +position +. +x +, +goal +-> +pose +. +pose +. +position +. +y +); +// Reset state for new action feedback +start_time_ += +clock_ +-> +now +(); +auto +blackboard += +bt_action_server_ +-> +getBlackboard +(); +blackboard +-> +set +< +int +> +( +"number_recoveries" +, +0 +); +// NOLINT +// Update the goal pose on the blackboard +blackboard +-> +set +< +geometry_msgs +:: +msg +:: +PoseStamped +> +( +goal_blackboard_id_ +, +goal +-> +pose +); +} +``` + +Language: unknown +File: onLoop +``` +void +NavigateToPoseNavigator::onLoop +() +{ +auto +feedback_msg += +std +:: +make_shared +< +ActionT +:: +Feedback +> +(); +geometry_msgs +:: +msg +:: +PoseStamped +current_pose += +...; +auto +blackboard += +bt_action_server_ +-> +getBlackboard +(); +nav_msgs +:: +msg +:: +Path +current_path +; +blackboard +-> +get +< +nav_msgs +:: +msg +:: +Path +> +( +path_blackboard_id_ +, +current_path +); +... +feedback_msg +-> +distance_remaining += +distance_remaining +; +feedback_msg +-> +estimated_time_remaining += +estimated_time_remaining +; +int +recovery_count += +0 +; +blackboard +-> +get +< +int +> +( +"number_recoveries" +, +recovery_count +); +feedback_msg +-> +number_of_recoveries += +recovery_count +; +feedback_msg +-> +current_pose += +current_pose +; +feedback_msg +-> +navigation_time += +clock_ +-> +now +() +- +start_time_ +; +bt_action_server_ +-> +publishFeedback +( +feedback_msg +); +} +``` + +Language: unknown +File: nav2_core::NavigatorBase +``` +#include +"pluginlib/class_list_macros.hpp" +PLUGINLIB_EXPORT_CLASS +( +nav2_bt_navigator +:: +NavigateToPoseNavigator +, +nav2_core +:: +NavigatorBase +) +``` + +Language: unknown +File: description +``` + + + +This +is +pure +point-to-point +navigation + + + + +``` + +Language: unknown +File: share +``` +pluginlib_export_plugin_description_file(nav2_core navigator_plugin.xml) + +``` + +Language: unknown +File: package.xml +``` + + +ament_cmake + + + +``` + +Language: unknown +File: nav2_params.yaml +``` +bt_navigator: + ros__parameters: + use_sim_time: true + global_frame: map + robot_base_frame: base_link + transform_tolerance: 0.1 + default_nav_to_pose_bt_xml: replace/with/path/to/bt.xml # or $(find-pkg-share my_package)/behavior_tree/my_nav_to_pose_bt.xml + default_nav_through_poses_bt_xml: replace/with/path/to/bt.xml # or $(find-pkg-share my_package)/behavior_tree/my_nav_through_poses_bt.xml + goal_blackboard_id: goal + goals_blackboard_id: goals + path_blackboard_id: path + navigators: ['navigate_to_pose', 'navigate_through_poses'] + navigate_to_pose: + plugin: "nav2_bt_navigator::NavigateToPoseNavigator" # In Iron and older versions, "/" was used instead of "::" + navigate_through_poses: + plugin: "nav2_bt_navigator::NavigateThroughPosesNavigator" # In Iron and older versions, "/" was used instead of "::" + +``` + +Language: unknown +File: . +``` +$ +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +params_file: += +/path/to/your_params_file.yaml + +``` diff --git "a/exported_docs/nav2/Writing a New Planner Plugin\357\203\201.txt" "b/exported_docs/nav2/Writing a New Planner Plugin\357\203\201.txt" new file mode 100644 index 0000000..fe7d968 --- /dev/null +++ "b/exported_docs/nav2/Writing a New Planner Plugin\357\203\201.txt" @@ -0,0 +1,537 @@ +Title: Writing a New Planner Plugin +URL: https://docs.nav2.org/plugin_tutorials/docs/writing_new_nav2planner_plugin.html#writing-new-nav2planner-plugin +Section: tuning/index.html +-------------------------------------------------------------------------------- + + +## Overview +This tutorial shows how to create your own planner plugin. + +## Requirements + + +## Tutorial Steps + + +## 1- Creating a new Planner Plugin +We will create a simple straight-line planner. +The annotated code in this tutorial can be found innavigation_tutorialsrepository as thenav2_straightline_planner. +This package can be considered as a reference for writing planner plugin. +Our example plugin inherits from the base classnav2_core::GlobalPlanner. The base class provides 5 pure virtual methods to implement a planner plugin. The plugin will be used by the planner server to compute trajectories. +Let’s learn more about the methods needed to write a planner plugin. +For this tutorial, we will be using methodsStraightLine::configure()andStraightLine::createPlan()to create straight-line planner. +In planners,configure()method must set member variables from ROS parameters and any initialization required, +Here,name_+".interpolation_resolution"is fetching the ROS parametersinterpolation_resolutionwhich is specific to our planner. Nav2 allows the loading of multiple plugins, and to keep things organized, each plugin is mapped to some ID/name. Now if we want to retrieve the parameters for that specific plugin, we use.as done in the above snippet. For example, our example planner is mapped to the name “GridBased” and to retrieve theinterpolation_resolutionparameter which is specific to “GridBased”, we usedGridbased.interpolation_resolution. In other words,GridBasedis used as a namespace for plugin-specific parameters. We will see more on this when we discuss the parameters file (or params file). +IncreatePlan()method, we need to create a path from the given start to goal poses. TheStraightLine::createPlan()is called using start pose and goal pose to solve the global path planning problem. Upon succeeding, it converts the path to thenav_msgs::msg::Pathand returns to the planner server. Below annotation shows the implementation of this method. +The remaining methods are not used but it’s mandatory to override them. As per the rules, we did override all but left them blank. + +## 2- Exporting the planner plugin +Now that we have created our custom planner, we need to export our planner plugin so that it will be visible to the planner server. Plugins are loaded at runtime and if they are not visible, then our planner server won’t be able to load it. In ROS 2, exporting and loading plugins is handled bypluginlib. +Coming back to our tutorial, classnav2_straightline_planner::StraightLineis loaded dynamically asnav2_core::GlobalPlannerwhich is our base class. +Note that it requires pluginlib to export out plugin’s class. Pluginlib would provide as macroPLUGINLIB_EXPORT_CLASSwhich does all the work of exporting. +It is good practice to place these lines at the end of the file, but technically, you can also write at the top. + +## 3- Pass the plugin name through params file +To enable the plugin, we need to modify thenav2_params.yamlfile as below to replace following params +with +In the above snippet, you can observe the mapping of ournav2_straightline_planner::StraightLineplanner to its idGridBased. To pass plugin-specific parameters, we have used.. + +## 4- Run StraightLine plugin +Run Turtlebot3 simulation with enabled navigation2. Detailed instruction how to make it are written atGetting Started. Below is shortcut command for that: +Then goto RViz and click on the “2D Pose Estimate” button at the top and point to the location on map as it was described inGetting Started. Robot will localize on the map and then click on “Navigation2 goal” and click on the pose where you want your planner to consider a goal pose. After that planner will plan the path and robot will start moving towards the goal. + +Code Examples: + +Language: unknown +File: configure() +``` +node_ += +parent +; +tf_ += +tf +; +name_ += +name +; +costmap_ += +costmap_ros +-> +getCostmap +(); +global_frame_ += +costmap_ros +-> +getGlobalFrameID +(); +// Parameter initialization +nav2_util +:: +declare_parameter_if_not_declared +( +node_ +, +name_ ++ +".interpolation_resolution" +, +rclcpp +:: +ParameterValue +( +0.1 +)); +node_ +-> +get_parameter +( +name_ ++ +".interpolation_resolution" +, +interpolation_resolution_ +); +``` + +Language: unknown +File: nav_msgs::msg::Path +``` +nav_msgs +:: +msg +:: +Path +global_path +; +// Checking if the goal and start state is in the global frame +if +( +start +. +header +. +frame_id +!= +global_frame_ +) +{ +RCLCPP_ERROR +( +node_ +-> +get_logger +(), +"Planner will only except start position from %s frame" +, +global_frame_ +. +c_str +()); +return +global_path +; +} +if +( +goal +. +header +. +frame_id +!= +global_frame_ +) +{ +RCLCPP_INFO +( +node_ +-> +get_logger +(), +"Planner will only except goal position from %s frame" +, +global_frame_ +. +c_str +()); +return +global_path +; +} +global_path +. +poses +. +clear +(); +global_path +. +header +. +stamp += +node_ +-> +now +(); +global_path +. +header +. +frame_id += +global_frame_ +; +// calculating the number of loops for current value of interpolation_resolution_ +int +total_number_of_loop += +std +:: +hypot +( +goal +. +pose +. +position +. +x +- +start +. +pose +. +position +. +x +, +goal +. +pose +. +position +. +y +- +start +. +pose +. +position +. +y +) +/ +interpolation_resolution_ +; +double +x_increment += +( +goal +. +pose +. +position +. +x +- +start +. +pose +. +position +. +x +) +/ +total_number_of_loop +; +double +y_increment += +( +goal +. +pose +. +position +. +y +- +start +. +pose +. +position +. +y +) +/ +total_number_of_loop +; +for +( +int +i += +0 +; +i +< +total_number_of_loop +; +++ +i +) +{ +geometry_msgs +:: +msg +:: +PoseStamped +pose +; +pose +. +pose +. +position +. +x += +start +. +pose +. +position +. +x ++ +x_increment +* +i +; +pose +. +pose +. +position +. +y += +start +. +pose +. +position +. +y ++ +y_increment +* +i +; +pose +. +pose +. +position +. +z += +0.0 +; +pose +. +pose +. +orientation +. +x += +0.0 +; +pose +. +pose +. +orientation +. +y += +0.0 +; +pose +. +pose +. +orientation +. +z += +0.0 +; +pose +. +pose +. +orientation +. +w += +1.0 +; +pose +. +header +. +stamp += +node_ +-> +now +(); +pose +. +header +. +frame_id += +global_frame_ +; +global_path +. +poses +. +push_back +( +pose +); +} +global_path +. +poses +. +push_back +( +goal +); +return +global_path +; +``` + +Language: unknown +File: nav2_core::GlobalPlanner +``` +#include +"pluginlib/class_list_macros.hpp" +PLUGINLIB_EXPORT_CLASS +( +nav2_straightline_planner +:: +StraightLine +, +nav2_core +:: +GlobalPlanner +) +``` + +Language: unknown +File: description +``` + + + +This +is +an +example +plugin +which +produces +straight +path. + + + +``` + +Language: unknown +File: share +``` +pluginlib_export_plugin_description_file(nav2_core global_planner_plugin.xml) + +``` + +Language: unknown +File: package.xml +``` + + +ament_cmake + + + +``` + +Language: unknown +File: plugin:MyPlugin::Plugin +``` +planner_server: + ros__parameters: + plugins: ["GridBased"] + use_sim_time: True + GridBased: + plugin: "nav2_navfn_planner::NavfnPlanner" # For Foxy and later. In Iron and older versions, "/" was used instead of "::" + tolerance: 2.0 + use_astar: false + allow_unknown: true + +``` + +Language: unknown +File: plugin:MyPlugin::Plugin +``` +planner_server: + ros__parameters: + plugins: ["GridBased"] + use_sim_time: True + GridBased: + plugin: "nav2_straightline_planner::StraightLine" + interpolation_resolution: 0.1 + +``` + +Language: unknown +File: . +``` +$ +ros2 +launch +nav2_bringup +tb3_simulation_launch.py +params_file: += +/path/to/your_params_file.yaml + +``` diff --git "a/exported_docs/nav2/XYTheta Iterator\357\203\201.txt" "b/exported_docs/nav2/XYTheta Iterator\357\203\201.txt" new file mode 100644 index 0000000..587133d --- /dev/null +++ "b/exported_docs/nav2/XYTheta Iterator\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: XYTheta Iterator +URL: https://docs.nav2.org/configuration/packages/dwb-params/iterator.html +Section: getting_started/index.html +-------------------------------------------------------------------------------- + + +## Parameters +: DWB plugin name defined in thecontroller_plugin_idsparameter inController Server. diff --git "a/exported_docs/ros2/Adding_a_frame_(Python)\357\203\201.txt" "b/exported_docs/ros2/Adding_a_frame_(Python)\357\203\201.txt" new file mode 100644 index 0000000..a3ff412 --- /dev/null +++ "b/exported_docs/ros2/Adding_a_frame_(Python)\357\203\201.txt" @@ -0,0 +1,137 @@ +Title: Adding a frame (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Adding-A-Frame-Py.html +Section: Installation +-------------------------------------------------------------------------------- + +Adding a frame (Python)Goal:Learn how to to add an extra frame to tf2.Tutorial level:IntermediateTime:15 minutesContentsBackgroundtf2 treeTasks1 Write the fixed frame broadcaster1.1 Examine the code1.2 Add an entry point1.3 Write the launch file1.4 Build1.5 Run2 Write the dynamic frame broadcaster2.1 Examine the code2.2 Add an entry point2.3 Write the launch file2.4 Build1.5 RunSummaryBackgroundIn previous tutorials, we recreated the turtle demo by writing atf2 broadcasterand atf2 listener. +This tutorial will teach you how to add extra fixed and dynamic frames to the transformation tree. +In fact, adding a frame in tf2 is very similar to creating the tf2 broadcaster, but this example will show you some additional features of tf2.For many tasks related to transformations, it is easier to think inside a local frame. +For example, it is easiest to reason about laser scan measurements in a frame at the center of the laser scanner. +tf2 allows you to define a local frame for each sensor, link, or joint in your system. +When transforming from one frame to another, tf2 will take care of all the hidden intermediate frame transformations that are introduced.tf2 treetf2 builds up a tree structure of frames and, thus, does not allow a closed loop in the frame structure. +This means that a frame only has one single parent, but it can have multiple children. +Currently, our tf2 tree contains three frames:world,turtle1andturtle2. +The two turtle frames are children of theworldframe. +If we want to add a new frame to tf2, one of the three existing frames needs to be the parent frame, and the new one will become its child frame.Tasks1 Write the fixed frame broadcasterIn our turtle example, we’ll add a new framecarrot1, which will be the child of theturtle1. +This frame will serve as the goal for the second turtle.Let’s first create the source files. +Go to thelearning_tf2_pypackage we created in the previous tutorials. +Inside thesrc/learning_tf2_py/learning_tf2_pydirectory download the fixed frame broadcaster code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.pywget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.pyIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py -o fixed_frame_tf2_broadcaster.pyOr in powershell:curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py -o fixed_frame_tf2_broadcaster.pyNow open the file calledfixed_frame_tf2_broadcaster.py.fromgeometry_msgs.msgimportTransformStampedimportrclpyfromrclpy.nodeimportNodefromtf2_rosimportTransformBroadcasterclassFixedFrameBroadcaster(Node):def__init__(self):super().__init__('fixed_frame_tf2_broadcaster')self.tf_broadcaster=TransformBroadcaster(self)self.timer=self.create_timer(0.1,self.broadcast_timer_callback)defbroadcast_timer_callback(self):t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='turtle1't.child_frame_id='carrot1't.transform.translation.x=0.0t.transform.translation.y=2.0t.transform.translation.z=0.0t.transform.rotation.x=0.0t.transform.rotation.y=0.0t.transform.rotation.z=0.0t.transform.rotation.w=1.0self.tf_broadcaster.sendTransform(t)defmain():rclpy.init()node=FixedFrameBroadcaster()try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown()The code is very similar to the tf2 broadcaster tutorial example and the only difference is that the transform here does not change over time.1.1 Examine the codeLet’s take a look at the key lines in this piece of code. +Here we create a new transform, from the parentturtle1to the new childcarrot1. +Thecarrot1frame is 2 meters offset in y axis in terms of theturtle1frame.t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='turtle1't.child_frame_id='carrot1't.transform.translation.x=0.0t.transform.translation.y=2.0t.transform.translation.z=0.01.2 Add an entry pointTo allow theros2runcommand to run your node, you must add the entry point tosetup.py(located in thesrc/learning_tf2_pydirectory).Add the following line between the'console_scripts':brackets:'fixed_frame_tf2_broadcaster = learning_tf2_py.fixed_frame_tf2_broadcaster:main',1.3 Write the launch fileNow let’s create a launch file for this example. +With your text editor, create a new file calledturtle_tf2_fixed_frame_demo_launch.pyin thesrc/learning_tf2_py/launchdirectory, and add the following lines:importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNodedefgenerate_launch_description():demo_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('learning_tf2_py'),'launch'),'/turtle_tf2_demo_launch.py']),)returnLaunchDescription([demo_nodes,Node(package='learning_tf2_py',executable='fixed_frame_tf2_broadcaster',name='fixed_broadcaster',),])This launch file imports the required packages and then creates ademo_nodesvariable that will store nodes that we created in the previous tutorial’s launch file.The last part of the code will add our fixedcarrot1frame to the turtlesim world using ourfixed_frame_tf2_broadcasternode.Node(package='learning_tf2_py',executable='fixed_frame_tf2_broadcaster',name='fixed_broadcaster',),1.4 BuildRunrosdepin the root of your workspace to check for missing dependencies.LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfStill in the root of your workspace, build your package:LinuxmacOSWindowscolcon build --packages-select learning_tf2_pycolcon build --packages-select learning_tf2_pycolcon build --merge-install --packages-select learning_tf2_pyOpen a new terminal, navigate to the root of your workspace, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bash#CMDcall install\setup.bat#Powershell.\install\setup.ps11.5 RunNow you can start the turtle broadcaster demo:ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo_launch.pyYou should notice that the newcarrot1frame appeared in the transformation tree.If you drive the first turtle around, you should notice that the behavior didn’t change from the previous tutorial, even though we added a new frame. +That’s because adding an extra frame does not affect the other frames and our listener is still using the previously defined frames.Therefore if we want our second turtle to follow the carrot instead of the first turtle, we need to change value of thetarget_frame. +This can be done two ways. +One way is to pass thetarget_frameargument to the launch file directly from the console:ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo_launch.py target_frame:=carrot1The second way is to update the launch file. +To do so, open theturtle_tf2_fixed_frame_demo_launch.pyfile, and add the'target_frame':'carrot1'parameter vialaunch_argumentsargument.defgenerate_launch_description():demo_nodes=IncludeLaunchDescription(...,launch_arguments={'target_frame':'carrot1'}.items(),)Now rebuild the package, restart theturtle_tf2_fixed_frame_demo_launch.py, and you’ll see the second turtle following the carrot instead of the first turtle!2 Write the dynamic frame broadcasterThe extra frame we published in this tutorial is a fixed frame that doesn’t change over time in relation to the parent frame. +However, if you want to publish a moving frame you can code the broadcaster to change the frame over time. +Let’s change ourcarrot1frame so that it changes relative toturtle1frame over time. +Go to thelearning_tf2_pypackage we created in the previous tutorial. +Inside thesrc/learning_tf2_py/learning_tf2_pydirectory download the dynamic frame broadcaster code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.pywget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.pyIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.py -o dynamic_frame_tf2_broadcaster.pyOr in powershell:curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.py -o dynamic_frame_tf2_broadcaster.pyNow open the file calleddynamic_frame_tf2_broadcaster.py:importmathfromgeometry_msgs.msgimportTransformStampedimportrclpyfromrclpy.nodeimportNodefromtf2_rosimportTransformBroadcasterclassDynamicFrameBroadcaster(Node):def__init__(self):super().__init__('dynamic_frame_tf2_broadcaster')self.tf_broadcaster=TransformBroadcaster(self)self.timer=self.create_timer(0.1,self.broadcast_timer_callback)defbroadcast_timer_callback(self):seconds,_=self.get_clock().now().seconds_nanoseconds()x=seconds*math.pit=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='turtle1't.child_frame_id='carrot1't.transform.translation.x=10*math.sin(x)t.transform.translation.y=10*math.cos(x)t.transform.translation.z=0.0t.transform.rotation.x=0.0t.transform.rotation.y=0.0t.transform.rotation.z=0.0t.transform.rotation.w=1.0self.tf_broadcaster.sendTransform(t)defmain():rclpy.init()node=DynamicFrameBroadcaster()try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown()2.1 Examine the codeInstead of a fixed definition of our x and y offsets, we are using thesin()andcos()functions on the current time so that the offset ofcarrot1is constantly changing.seconds,_=self.get_clock().now().seconds_nanoseconds()x=seconds*math.pi...t.transform.translation.x=10*math.sin(x)t.transform.translation.y=10*math.cos(x)2.2 Add an entry pointTo allow theros2runcommand to run your node, you must add the entry point tosetup.py(located in thesrc/learning_tf2_pydirectory).Add the following line between the'console_scripts':brackets:'dynamic_frame_tf2_broadcaster = learning_tf2_py.dynamic_frame_tf2_broadcaster:main',2.3 Write the launch fileTo test this code, create a new launch fileturtle_tf2_dynamic_frame_demo_launch.pyin thesrc/learning_tf2_py/launchdirectory and paste the following code:importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNodedefgenerate_launch_description():demo_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('learning_tf2_py'),'launch'),'/turtle_tf2_demo_launch.py']),launch_arguments={'target_frame':'carrot1'}.items(),)returnLaunchDescription([demo_nodes,Node(package='learning_tf2_py',executable='dynamic_frame_tf2_broadcaster',name='dynamic_broadcaster',),])2.4 BuildRunrosdepin the root of your workspace to check for missing dependencies.LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfStill in the root of your workspace, build your package:LinuxmacOSWindowscolcon build --packages-select learning_tf2_pycolcon build --packages-select learning_tf2_pycolcon build --merge-install --packages-select learning_tf2_pyOpen a new terminal, navigate to the root of your workspace, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bash#CMDcall install\setup.bat#Powershell.\install\setup.ps11.5 RunNow you can start the dynamic frame demo:ros2 launch learning_tf2_py turtle_tf2_dynamic_frame_demo_launch.pyYou should see that the second turtle is following the carrot’s position that is constantly changing.SummaryIn this tutorial, you learned about the tf2 transformation tree, its structure, and its features. +You also learned that it is easiest to think inside a local frame, and learned to add extra fixed and dynamic frames for that local frame. + +Code Examples: + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py -o fixed_frame_tf2_broadcaster.py + +Language: unknown +curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py -o fixed_frame_tf2_broadcaster.py + +Language: unknown +fromgeometry_msgs.msgimportTransformStampedimportrclpyfromrclpy.nodeimportNodefromtf2_rosimportTransformBroadcasterclassFixedFrameBroadcaster(Node):def__init__(self):super().__init__('fixed_frame_tf2_broadcaster')self.tf_broadcaster=TransformBroadcaster(self)self.timer=self.create_timer(0.1,self.broadcast_timer_callback)defbroadcast_timer_callback(self):t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='turtle1't.child_frame_id='carrot1't.transform.translation.x=0.0t.transform.translation.y=2.0t.transform.translation.z=0.0t.transform.rotation.x=0.0t.transform.rotation.y=0.0t.transform.rotation.z=0.0t.transform.rotation.w=1.0self.tf_broadcaster.sendTransform(t)defmain():rclpy.init()node=FixedFrameBroadcaster()try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown() + +Language: unknown +t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='turtle1't.child_frame_id='carrot1't.transform.translation.x=0.0t.transform.translation.y=2.0t.transform.translation.z=0.0 + +Language: unknown +'fixed_frame_tf2_broadcaster = learning_tf2_py.fixed_frame_tf2_broadcaster:main', + +Language: unknown +importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNodedefgenerate_launch_description():demo_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('learning_tf2_py'),'launch'),'/turtle_tf2_demo_launch.py']),)returnLaunchDescription([demo_nodes,Node(package='learning_tf2_py',executable='fixed_frame_tf2_broadcaster',name='fixed_broadcaster',),]) + +Language: unknown +Node(package='learning_tf2_py',executable='fixed_frame_tf2_broadcaster',name='fixed_broadcaster',), + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --merge-install --packages-select learning_tf2_py + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +#CMDcall install\setup.bat#Powershell.\install\setup.ps1 + +Language: unknown +ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo_launch.py + +Language: unknown +ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo_launch.py target_frame:=carrot1 + +Language: unknown +defgenerate_launch_description():demo_nodes=IncludeLaunchDescription(...,launch_arguments={'target_frame':'carrot1'}.items(),) + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.py + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.py + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.py -o dynamic_frame_tf2_broadcaster.py + +Language: unknown +curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/dynamic_frame_tf2_broadcaster.py -o dynamic_frame_tf2_broadcaster.py + +Language: unknown +importmathfromgeometry_msgs.msgimportTransformStampedimportrclpyfromrclpy.nodeimportNodefromtf2_rosimportTransformBroadcasterclassDynamicFrameBroadcaster(Node):def__init__(self):super().__init__('dynamic_frame_tf2_broadcaster')self.tf_broadcaster=TransformBroadcaster(self)self.timer=self.create_timer(0.1,self.broadcast_timer_callback)defbroadcast_timer_callback(self):seconds,_=self.get_clock().now().seconds_nanoseconds()x=seconds*math.pit=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='turtle1't.child_frame_id='carrot1't.transform.translation.x=10*math.sin(x)t.transform.translation.y=10*math.cos(x)t.transform.translation.z=0.0t.transform.rotation.x=0.0t.transform.rotation.y=0.0t.transform.rotation.z=0.0t.transform.rotation.w=1.0self.tf_broadcaster.sendTransform(t)defmain():rclpy.init()node=DynamicFrameBroadcaster()try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown() + +Language: unknown +seconds,_=self.get_clock().now().seconds_nanoseconds()x=seconds*math.pi...t.transform.translation.x=10*math.sin(x)t.transform.translation.y=10*math.cos(x) + +Language: unknown +'dynamic_frame_tf2_broadcaster = learning_tf2_py.dynamic_frame_tf2_broadcaster:main', + +Language: unknown +importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch_ros.actionsimportNodedefgenerate_launch_description():demo_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('learning_tf2_py'),'launch'),'/turtle_tf2_demo_launch.py']),launch_arguments={'target_frame':'carrot1'}.items(),)returnLaunchDescription([demo_nodes,Node(package='learning_tf2_py',executable='dynamic_frame_tf2_broadcaster',name='dynamic_broadcaster',),]) + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --merge-install --packages-select learning_tf2_py + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +#CMDcall install\setup.bat#Powershell.\install\setup.ps1 + +Language: unknown +ros2 launch learning_tf2_py turtle_tf2_dynamic_frame_demo_launch.py diff --git "a/exported_docs/ros2/Adding_physical_and_collision_properties\357\203\201.txt" "b/exported_docs/ros2/Adding_physical_and_collision_properties\357\203\201.txt" new file mode 100644 index 0000000..252cc90 --- /dev/null +++ "b/exported_docs/ros2/Adding_physical_and_collision_properties\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: Adding physical and collision properties +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/URDF/Adding-Physical-and-Collision-Properties-to-a-URDF-Model.html +Section: Installation +-------------------------------------------------------------------------------- + +Adding physical and collision propertiesGoal:Learn how to add collision and inertial properties to links, and how to add joint dynamics to joints.Tutorial level:IntermediateTime:10 minutesContentsCollisionPhysical PropertiesInertiaContact CoefficientsJoint DynamicsOther TagsNext StepsIn this tutorial, we’ll look at how to add some basic physical properties to your URDF model and how to specify its collision properties.CollisionSo far, we’ve only specified our links with a single sub-element,visual, which defines (not surprisingly) what the robot looks like. +However, in order to get collision detection to work or to simulate the robot, we need to define acollisionelement as well.Here is the new urdfwith collision and physical properties.Here is the code for our new base link.
The collision element is a direct subelement of the link object, at the same level as the visual tag.The collision element defines its shape the same way the visual element does, with a geometry tag. +The format for the geometry tag is exactly the same here as with the visual.You can also specify an origin in the same way as a subelement of the collision tag (as with the visual).In many cases, you’ll want the collision geometry and origin to be exactly the same as the visual geometry and origin. +However, there are two main cases where you wouldn’t:Quicker Processing. Doing collision detection for two meshes is a lot more computational complex than for two simple geometries. +Hence, you may want to replace the meshes with simpler geometries in the collision element.Safe Zones. You may want to restrict movement close to sensitive equipment. +For instance, if we didn’t want anything to collide with R2D2’s head, we might define the collision geometry to be a cylinder encasing his head to prevent anything from getting too close to his head.Physical PropertiesIn order to get your model to simulate properly, you need to define several physical properties of your robot, i.e. +the properties that a physics engine like Gazebo would need.InertiaEvery link element being simulated needs an inertial tag. +Here is a simple one.This element is also a subelement of the link object.The mass is defined in kilograms.The 3x3 rotational inertia matrix is specified with the inertia element. +Since this is symmetrical, it can be represented by only 6 elements, as such.ixxixyixzixyiyyiyzixziyzizzThis information can be provided to you by modeling programs such as MeshLab. +The inertia of geometric primitives (cylinder, box, sphere) can be computed using Wikipedia’slist of moment of inertia tensors(and is used in the above example).The inertia tensor depends on both the mass and the distribution of mass of the object. +A good first approximation is to assume equal distribution of mass in the volume of the object and compute the inertia tensor based on the object’s shape, as outlined above.If unsure what to put, a matrix with ixx/iyy/izz=1e-3 or smaller is often a reasonable default for a mid-sized link (it corresponds to a box of 0.1 m side length with a mass of 0.6 kg). +The identity matrix is a particularly bad choice, since it is often much too high (it corresponds to a box of 0.1 m side length with a mass of 600 kg!).You can also specify an origin tag to specify the center of gravity and the inertial reference frame (relative to the link’s reference frame).When using realtime controllers, inertia elements of zero (or almost zero) can cause the robot model to collapse without warning, and all links will appear with their origins coinciding with the world origin.Contact CoefficientsYou can also define how the links behave when they are in contact with one another. +This is done with a subelement of the collision tag called contact_coefficients. +There are three attributes to specify:mu -Friction coefficientkp -Stiffness coefficientkd -Dampening coefficientJoint DynamicsHow the joint moves is defined by the dynamics tag for the joint. +There are two attributes here:friction- The physical static friction. +For prismatic joints, the units are Newtons. +For revolving joints, the units are Newton meters.damping- The physical damping value. +For prismatic joints, the units are Newton seconds per meter. +For revolving joints, Newton meter seconds per radian.If not specified, these coefficients default to zero.Other TagsIn the realm of pure URDF (i.e. excluding Gazebo-specific tags), there are two remaining tags to help define the joints: calibration and safety controller. +Check out thespec, as they are not included in this tutorial.Next StepsReduce the amount of code and annoying math you have to do byusing xacro. + +Code Examples: + +Language: unknown + + +Language: unknown + diff --git "a/exported_docs/ros2/Advanced_Concepts\357\203\201.txt" "b/exported_docs/ros2/Advanced_Concepts\357\203\201.txt" new file mode 100644 index 0000000..6054b6f --- /dev/null +++ "b/exported_docs/ros2/Advanced_Concepts\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Advanced Concepts +URL: https://docs.ros.org/en/jazzy/Concepts/Advanced.html +Section: Installation +-------------------------------------------------------------------------------- + +Advanced ConceptsThese conceptual documents are intended for developers who plan to modify or contribute to the ROS 2 core.The build systemInternal ROS 2 interfacesROS 2 middleware implementations \ No newline at end of file diff --git "a/exported_docs/ros2/Alternatives\357\203\201.txt" "b/exported_docs/ros2/Alternatives\357\203\201.txt" new file mode 100644 index 0000000..2bfd934 --- /dev/null +++ "b/exported_docs/ros2/Alternatives\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Alternatives +URL: https://docs.ros.org/en/jazzy/Installation/Alternatives.html +Section: Installation +-------------------------------------------------------------------------------- + +AlternativesA list of alternative ways to install ROS 2 – whether it’s by building from source or installing a binary.Ubuntu (source)Ubuntu (binary)Windows (source)RHEL (source)RHEL (binary)macOS (source)Latest development (source) \ No newline at end of file diff --git "a/exported_docs/ros2/Ardent_Apalone_(ardent)\357\203\201.txt" "b/exported_docs/ros2/Ardent_Apalone_(ardent)\357\203\201.txt" new file mode 100644 index 0000000..51e3910 --- /dev/null +++ "b/exported_docs/ros2/Ardent_Apalone_(ardent)\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Ardent Apalone (ardent) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Ardent-Apalone.html +Section: Installation +-------------------------------------------------------------------------------- + +Ardent Apalone (ardent)Table of ContentsSupported PlatformsFeaturesNew features in this ROS 2 releaseChanges since Beta 3 releaseKnown IssuesWelcome to the first non-beta release of ROS 2 software namedArdent Apalone!Supported PlatformsThis version of ROS 2 is supported on three platforms:Ubuntu 16.04 (Xenial)Mac macOS 10.12 (Sierra)Windows 10Binary packages as well as instructions for how to compile from source are provided for all 3 platforms (seeinstall instructionsas well asdocumentation).FeaturesNew features in this ROS 2 releaseDistributed discovery, publish / subscribe, request / response communicationProvided by a C APIImplemented using different vendors:eProsima’s Fast RTPS as well as ADLINK’s OpenSplice (from binary and source)RTI’s Connext (only from source)Numerous quality of service settings for handling non-ideal networksDDS Security support (with Connext and Fast RTPS)C++ and Python 3 client librariesSharing common code in C to unify the implementationExecution model separated from the nodes, composable nodesNode-specific parameters (only in C++ atm)Life cycle (only in C++ atm)Optionally intra-process communication using the same API (only in C++)Message definitions (with bounded arrays and strings as well as default values)Command line tools (e.g.ros2run)rvizwith a few display types (the Windows version will likely follow in a few weeks)File system-based resource index (querying information without recursive crawling)Realtime safe code paths for pub / sub (with compatible DDS implementations only)Bridge between ROS 1 and ROS 2HSR demosee Beta 3Turtlebot demosee Beta 2For a more detailed description please see theFeaturespage.Changes since Beta 3 releaseImprovements since the Beta 3 release:rvizDifferent initialization options for message data structures in C++ (seedesign doc)Logging API improvements, now also used in the demosTime support in C++ with different clockswait-for-service support in the Python client libraryDraft implementation ofREP 149specifying format 3 of the package manifest filesKnown IssuesFast RTPS performance with larger data like the image demoUsing Connext it is currently not allowed for two topics with the same base name but different namespaces to have a different type (seeissue).Listing of node names (e.g. usingros2nodelist) does not work across some rmw implementations.On Windows Python launch files might hang when trying to abort usingCtrl-C(seeissue). In order to continue using the shell which is blocked by the hanging command you might want to end the hanging Python process using the process monitor. \ No newline at end of file diff --git "a/exported_docs/ros2/Basic_Concepts\357\203\201.txt" "b/exported_docs/ros2/Basic_Concepts\357\203\201.txt" new file mode 100644 index 0000000..5568764 --- /dev/null +++ "b/exported_docs/ros2/Basic_Concepts\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Basic Concepts +URL: https://docs.ros.org/en/jazzy/Concepts/Basic.html +Section: Installation +-------------------------------------------------------------------------------- + +Basic ConceptsROS 2 is a middleware based on a strongly-typed, anonymous publish/subscribe mechanism that allows for message passing between different processes.At the heart of any ROS 2 system is the ROS graph. +The ROS graph refers to the network of nodes in a ROS system and the connections between them by which they communicate.These are the concepts that will help you get started understanding the basics of ROS 2.NodesDiscoveryInterfacesTopicsServicesActionsParametersIntrospection with command line toolsLaunchClient libraries \ No newline at end of file diff --git "a/exported_docs/ros2/Beginner:_CLI_tools\357\203\201.txt" "b/exported_docs/ros2/Beginner:_CLI_tools\357\203\201.txt" new file mode 100644 index 0000000..d29b540 --- /dev/null +++ "b/exported_docs/ros2/Beginner:_CLI_tools\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Beginner: CLI tools +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools.html +Section: Installation +-------------------------------------------------------------------------------- + +Beginner: CLI toolsConfiguring environmentUsingturtlesim,ros2, andrqtUnderstanding nodesUnderstanding topicsUnderstanding servicesUnderstanding parametersUnderstanding actionsUsingrqt_consoleto view logsLaunching nodesRecording and playing back data \ No newline at end of file diff --git "a/exported_docs/ros2/Beginner:_Client_libraries\357\203\201.txt" "b/exported_docs/ros2/Beginner:_Client_libraries\357\203\201.txt" new file mode 100644 index 0000000..61c757c --- /dev/null +++ "b/exported_docs/ros2/Beginner:_Client_libraries\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Beginner: Client libraries +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries.html +Section: Installation +-------------------------------------------------------------------------------- + +Beginner: Client librariesUsingcolconto build packagesCreating a workspaceCreating a packageWriting a simple publisher and subscriber (C++)Writing a simple publisher and subscriber (Python)Writing a simple service and client (C++)Writing a simple service and client (Python)Creating custom msg and srv filesImplementing custom interfacesUsing parameters in a class (C++)Using parameters in a class (Python)Usingros2doctorto identify issuesCreating and using plugins (C++) \ No newline at end of file diff --git "a/exported_docs/ros2/Beta_2_(r2b2)\357\203\201.txt" "b/exported_docs/ros2/Beta_2_(r2b2)\357\203\201.txt" new file mode 100644 index 0000000..7ca5220 --- /dev/null +++ "b/exported_docs/ros2/Beta_2_(r2b2)\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Beta 2 (r2b2) +URL: https://docs.ros.org/en/jazzy/Releases/Beta2-Overview.html +Section: Installation +-------------------------------------------------------------------------------- + +Beta 2 (r2b2)Table of ContentsSupported PlatformsFeaturesImprovements since Beta 1 releaseNew demo applicationSelected features from previous Alpha/Beta releasesKnown issuesSupported PlatformsWe support ROS 2 Beta 2 on three platforms: Ubuntu 16.04 (Xenial), macOS 10.12 (Sierra), and Windows 10. +We provide both binary packages and instructions for how to compile from source for all 3 platforms (seeinstall instructionsas well asdocumentation).FeaturesImprovements since Beta 1 releaseDDS_Security support (aka SROS2, seesros2)Debian packages for Ubuntu XenialTypesupport has been redesigned so that you only build a single executable and can choose one of the available RMW implementations by setting an environment variable (seedocumentation).Namespace support for nodes and topics (seedesign article, see known issues below).A set of command-line tools using the extensibleros2command (seeconceptual article).A set of macros for logging messages in C / C++ (see API docs ofrcutils).New demo applicationTurtlebot 2 demosusing the following repositories that have been (partially) converted to ROS 2 (Linux only):ros_astra_cameradepthimage_to_laserscanpcl_conversionscartographercartographer_rosceres-solvernavigationteleop_twist_keyboardjoystick_driversteleop_twist_joyDummy_robot demo:robot_modelrobot_state_publisherSelected features from previous Alpha/Beta releasesFor the complete list, seeearlier release notes.C++ and Python implementations of ROS 2 client libraries including APIs for:Publishing and subscribing to ROS topicsRequesting and replying ROS services (synchronous (C++ only) and asynchronous)Getting and setting ROS parameters (C++ only, synchronous and asynchronous)Timer callbacksSupport for interoperability between multiple DDS/RTPS implementationseProsima Fast RTPS is our default implementation, and is included in the binary packagesRTI Connext is supported: build from source to try it outWe initially supported PrismTech OpenSplice but support for it is currently on holdA graph API for network eventsDistributed discoveryRealtime safe code paths for publish and subscribe with compatible DDS implementation (only Connext at the moment)Support for custom allocatorsROS 1 <-> ROS 2 dynamic bridge nodeExecutor threading model (C++ only)Component model to compose nodes at compile / link / runtimeManaged component using a standard lifecycleExtended.msgformat with new features:Bounded arraysDefault valuesKnown issuesWe’re tracking issues in various repositories, but the main entry point is theros2/ros2 issue trackerWe’d like to highlight aknown issuethat we are looking into which doesn’t allow two topics with the same base name but different namespaces to have a different type when usingrmw_connext_cpp.Services with long responses are not working with Fast-RTPS. The fix, while not being part of beta2, is available upstream so you can work around this issue by building from source using Fast-RTPS master branch. \ No newline at end of file diff --git "a/exported_docs/ros2/Beta_3_(r2b3)\357\203\201.txt" "b/exported_docs/ros2/Beta_3_(r2b3)\357\203\201.txt" new file mode 100644 index 0000000..a3e16ef --- /dev/null +++ "b/exported_docs/ros2/Beta_3_(r2b3)\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Beta 3 (r2b3) +URL: https://docs.ros.org/en/jazzy/Releases/Beta3-Overview.html +Section: Installation +-------------------------------------------------------------------------------- + +Beta 3 (r2b3)Table of ContentsSupported PlatformsFeaturesImprovements since Beta 2 releaseNew demo applicationSelected features from previous Alpha/Beta releasesKnown issuesSupported PlatformsWe support ROS 2 Beta 3 on three platforms: Ubuntu 16.04 (Xenial), macOS 10.12 (Sierra), and Windows 10. +We provide both binary packages and instructions for how to compile from source for all 3 platforms (seeinstall instructionsas well asdocumentation).FeaturesImprovements since Beta 2 releaseExecution model in Python, many fixes to memory management in Python C extensionExperimental rewrite ofros_controlExposure of DDS implementation-specific symbols to users (for Fast RTPS and Connext) (seeexample)LoggingAPIin PythonFixed several memory leaks and race conditions in various packagesReadded support for OpenSplice (on Linux and Windows atm) provided by PrismTechUse bloom (without patches) to make ROS 2 releasesNew demo applicationHSR demoRemote control a HSR robot using a ROS 2 joystick controllerRunning theros1_bridgein a Docker container on the HSR (since the robot is running ROS 1 on Ubuntu Trusty)Run a ROS 2 development version ofrvizto visualize sensor data from the robot etc. (seevideo)Selected features from previous Alpha/Beta releasesFor the complete list, seeearlier release notes.C++ and Python implementations of ROS 2 client libraries including APIs for:Publishing and subscribing to ROS topicsRequesting and replying ROS services (synchronous (C++ only) and asynchronous)Getting and setting ROS parameters (C++ only, synchronous and asynchronous)Timer callbacksSupport for interoperability between multiple DDS/RTPS implementationseProsima Fast RTPS is our default implementation, and is included in the binary packagesRTI Connext is supported: build from source to try it outPrismTech OpenSplice: see limitations belowA graph API for network eventsDistributed discoveryRealtime safe code paths for publish and subscribe with compatible DDS implementation (only Connext at the moment)Support for custom allocatorsROS 1 <-> ROS 2 dynamic bridge nodeExecutor threading model (C++ and Python)Component model to compose nodes at compile / link / runtimeManaged component using a standard lifecycleExtended.msgformat with new features:Bounded arraysDefault valuesKnown issuesOn Windows Python launch files might hang when trying to abort usingCtrl-C(seeissue). In order to continue using the shell which is blocked by the hanging command you might want to end the hanging Python process using the process monitor.OpenSplice support is currently not available for MacOS. Alsoaccess to native handlesis not yet implemented.Using Connext it is currently not allowed for two topics with the same base name but different namespaces to have a different type (seeissue). \ No newline at end of file diff --git "a/exported_docs/ros2/Bouncy_Bolson_(bouncy)\357\203\201.txt" "b/exported_docs/ros2/Bouncy_Bolson_(bouncy)\357\203\201.txt" new file mode 100644 index 0000000..a2126d6 --- /dev/null +++ "b/exported_docs/ros2/Bouncy_Bolson_(bouncy)\357\203\201.txt" @@ -0,0 +1,12 @@ +Title: Bouncy Bolson (bouncy) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Bouncy-Bolson.html +Section: Installation +-------------------------------------------------------------------------------- + +Bouncy Bolson (bouncy)Table of ContentsSupported PlatformsFeaturesNew features in this ROS 2 releaseChanges since the Ardent releaseKnown IssuesBouncy Bolsonis the second release of ROS 2.Supported PlatformsThis version of ROS 2 is supported on four platforms (seeREP 2000for full details):Ubuntu 18.04 (Bionic)Debian packages for amd64 as well as arm64Ubuntu 16.04 (Xenial)no Debian packages but building from source is supportedMac macOS 10.12 (Sierra)Windows 10 with Visual Studio 2017Binary packages as well as instructions for how to compile from source are provided (seeinstall instructionsas well asdocumentation).FeaturesNew features in this ROS 2 releaseNew launch systemfeaturing a much more capable and flexible Python API.Parameters can be passed ascommand line argumentsto C++ executables.Static remapping viacommand line arguments.Various improvements to the Python client library.Support for publishing and subscribing to serialized data. +This is the foundation for the upcoming work towards a native rosbag implementation.Morecommand line tools, e.g. for working with parameters and lifecycle states.Binary packages / fat archives support three RMW implementations by default (without the need to build from source):eProsima’s Fast RTPS (default)RTI’s ConnextADLINK’s OpenSpliceFor an overview of all features available, including those from earlier releases, please see theFeaturespage.Changes since the Ardent releaseChanges since theArdent Apalonerelease:The Python packagelaunchhas been redesigned. +The previous Python API has been moved into a submodulelaunch.legacy. +You can update existing launch files to continue to use the legacy API if a transition to the new Python API is not desired.The ROS topic names containing namespaces are mapped to DDS topics including their namespaces. +DDS partitions are not being used anymore for this.The recommended build tool is nowcolconinstead ofament_tools. +This switch has noimplicationsfor the code in each ROS 2 package. +The install instructions have been updated and theread-the-docs pagedescribes how to map an existingament_toolscall tocolcon.The argument order ofthis rclcpp::Node::create_subscription() signaturehas been modified.Known IssuesNew-style launch filesmay hang on shutdownfor some combinations of platform and RMW implementation.Static remapping of namespacesnot working correctlywhen addressed to a particular node.Opensplice error messages may be printedwhen usingros2paramandros2lifecyclecommand-line tools. \ No newline at end of file diff --git "a/exported_docs/ros2/Building_ROS_2_with_tracing\357\203\201.txt" "b/exported_docs/ros2/Building_ROS_2_with_tracing\357\203\201.txt" new file mode 100644 index 0000000..21e9c0f --- /dev/null +++ "b/exported_docs/ros2/Building_ROS_2_with_tracing\357\203\201.txt" @@ -0,0 +1,45 @@ +Title: Building ROS 2 with tracing +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Building-ROS-2-with-Tracing.html +Section: Installation +-------------------------------------------------------------------------------- + +Building ROS 2 with tracingTable of ContentsPrerequisitesBuild configurationsBuilding without tracepointsBuilding without instrumentationValidatingTracing instrumentation is included in the ROS 2 source code, and Linux installations of ROS 2 include the LTTng tracer as a dependency. +Therefore, ROS 2 can be traced out-of-the-box on Linux.However, ROS 2 can be built from source to remove the tracepoints or completely remove the instrumentation. +This guide shows how to do that. +For more information, seethe repository.NoteThis guide only applies to Linux systems.PrerequisitesSet up your system to build ROS 2 from source. +Seethe source installation pagefor more information.Build configurationsThe ROS 2 tracing instrumentation is split into two components: function instrumentation and tracepoints. +First, a ROS 2 core package (e.g.,rclcpp) calls a function provided by thetracetoolspackage. +Then, that function triggers a tracepoint, which records data if the tracepoint is enabled at runtime.By default, if the tracer is notconfigured to trace or if the tracepoints are not enabled, they will have virtually no impact on the execution. +However, the tracepoints can still be removed through a CMake option. +Furthermore, the functions can be completely removed through a CMake option, which implies that tracepoints are also removed.Building without tracepointsThis step depends on whether you arebuilding ROS 2 from sourceor using ROS 2 binaries (deb packagesorbinary archive). +To remove the tracepoints, (re)buildtracetoolsand set theTRACETOOLS_TRACEPOINTS_EXCLUDEDCMake option toON:Source installationBinary installationcd~/ros2_jazzy +colconbuild--packages-selecttracetools--cmake-clean-cache--cmake-args-DTRACETOOLS_TRACEPOINTS_EXCLUDED=ONClone theros2_tracingrepository into your workspace and build:cd~/ws +gitclonehttps://github.com/ros2/ros2_tracing.git-bjazzysrc/ros2_tracing +colconbuild--packages-selecttracetools--cmake-args-DTRACETOOLS_TRACEPOINTS_EXCLUDED=ONBuilding without instrumentationTo completely remove both tracepoints and function calls,build ROS 2 from sourceand set theTRACETOOLS_DISABLEDCMake option toON:cd~/ros2_jazzy +colconbuild--cmake-args-DTRACETOOLS_DISABLED=ON--no-warn-unused-cliValidatingValidate that tracing is disabled:cd~/wssourceinstall/setup.bash +ros2runtracetoolsstatusIt should print out:Without tracepointsWithout instrumentationTracingdisabledTracingdisabledthroughconfigurationIf something else is printed, then something went wrong. + +Code Examples: + +Language: unknown +cd~/ros2_jazzy +colconbuild--packages-selecttracetools--cmake-clean-cache--cmake-args-DTRACETOOLS_TRACEPOINTS_EXCLUDED=ON + +Language: unknown +cd~/ws +gitclonehttps://github.com/ros2/ros2_tracing.git-bjazzysrc/ros2_tracing +colconbuild--packages-selecttracetools--cmake-args-DTRACETOOLS_TRACEPOINTS_EXCLUDED=ON + +Language: unknown +cd~/ros2_jazzy +colconbuild--cmake-args-DTRACETOOLS_DISABLED=ON--no-warn-unused-cli + +Language: unknown +cd~/wssourceinstall/setup.bash +ros2runtracetoolsstatus + +Language: unknown +Tracingdisabled + +Language: unknown +Tracingdisabledthroughconfiguration diff --git "a/exported_docs/ros2/Building_a_Custom_RViz_Display\357\203\201.txt" "b/exported_docs/ros2/Building_a_Custom_RViz_Display\357\203\201.txt" new file mode 100644 index 0000000..d5dfc70 --- /dev/null +++ "b/exported_docs/ros2/Building_a_Custom_RViz_Display\357\203\201.txt" @@ -0,0 +1,72 @@ +Title: Building a Custom RViz Display +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/RViz/RViz-Custom-Display/RViz-Custom-Display.html +Section: Installation +-------------------------------------------------------------------------------- + +Building a Custom RViz DisplayBackgroundThere are many types of data that have existing visualizations in RViz. However, if there is a message type that does +not yet have a plugin to display it, there are two choices to see it in RViz.Convert the message to another type, such asvisualization_msgs/Marker.Write a Custom RViz Display.With the first option, there is more network traffic and limitations to how the data can be represented. It is also quick and flexible. +The latter option is explained in this tutorial. It takes a bit of work, but can lead to much richer visualizations.All of the code for this tutorial can be found inthis repository. +In order to see the incremental progress of the plugin written in this tutorial, +the repository has different branches (step2,step3…) that can each be compiled and run as you go.Point2D MessageWe’ll be playing with a toy message defined in therviz_plugin_tutorial_msgspackage:Point2D.msg:std_msgs/Headerheaderfloat64xfloat64yBoilerplate for Basic PluginStrap in, there’s a lot of code. +You can view the full version of this code with the branch namestep1.Header FileHere are the contents ofpoint_display.hpp#ifndef RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#define RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#include#includenamespacerviz_plugin_tutorial{classPointDisplay:publicrviz_common::MessageFilterDisplay{Q_OBJECTprotected:voidprocessMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg)override;};}// namespace rviz_plugin_tutorial#endif// RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_We’re implementing theMessageFilterDisplayclass which can be used with any message with astd_msgs/Header.The class is templated with ourPoint2Dmessage type.For reasons outside the scope of this tutorial, you need theQ_OBJECTmacro in there to get the QT parts of the GUI to work.processMessageis the only method that needs to be implemented, which we’ll do in the cpp file.Source Filepoint_display.cpp#include#includenamespacerviz_plugin_tutorial{voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<header.frame_id);}}// namespace rviz_plugin_tutorial#includePLUGINLIB_EXPORT_CLASS(rviz_plugin_tutorial::PointDisplay,rviz_common::Display)The logging is not strictly necessary, but helps with debugging.In order for RViz to find our plugin, we need thisPLUGINLIBinvocation in our code (as well as other things below).package.xmlWe need the following three dependencies in our package.xml:pluginlibrviz_commonrviz_plugin_tutorial_msgsrviz_common_plugins.xmlThis is standardpluginlibcode.The librarypathis the name of the library we’ll assign in the CMake.The class should match thePLUGINLIBinvocation from above.We’ll come back to the description later, I promise.CMakeLists.txtAdd the following lines to the top of the standard boilerplate.find_package(ament_cmake_rosREQUIRED)find_package(pluginlibREQUIRED)find_package(rviz_commonREQUIRED)find_package(rviz_plugin_tutorial_msgsREQUIRED)set(CMAKE_AUTOMOCON)qt5_wrap_cpp(MOC_FILESinclude/rviz_plugin_tutorial/point_display.hpp)add_library(point_displaysrc/point_display.cpp${MOC_FILES})target_include_directories(point_displayPUBLIC$$)ament_target_dependencies(point_displaypluginlibrviz_commonrviz_plugin_tutorial_msgs)install(TARGETSpoint_displayEXPORTexport_rviz_plugin_tutorialARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)install(DIRECTORYinclude/DESTINATIONinclude)install(FILESrviz_common_plugins.xmlDESTINATIONshare/${PROJECT_NAME})ament_export_include_directories(include)ament_export_targets(export_rviz_plugin_tutorial)pluginlib_export_plugin_description_file(rviz_commonrviz_common_plugins.xml)To generate the proper Qt files, we need toTurnCMAKE_AUTOMOCon.Wrap the headers by callingqt5_wrap_cppwith each header that hasQ_OBJECTin it.Include theMOC_FILESin the library alongside our other cpp files.Note that if you do NOT wrap your header files, you may get an error message when attempting to load the plugin at runtime, along the lines of:[rviz2]: PluginlibFactory: The plugin for class 'rviz_plugin_tutorial::PointDisplay' failed to load. Error: Failed to load library /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library LoadLibrary error: /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so: undefined symbol: _ZTVN20rviz_plugin_tutorial12PointDisplayE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84A lot of the other code ensures that the plugin portion works. +Namely, callingpluginlib_export_plugin_description_fileis essential to getting RViz to find your new plugin.Testing it outCompile your code and runrviz2. +You should be able to add your new plugin by clickingAddin the bottom left, and then selecting your package/plugin.Initially, the display will be in an error state because you have yet to assign a topic.If we put the topic/pointin, it should load fine but not display anything.You can publish messages with the following command:ros2topicpub/pointrviz_plugin_tutorial_msgs/msg/Point2D"{header: {frame_id: map}, x: 1, y: 2}"-r0.5That should result in the “We got a message” logging to appear in thestdoutof RViz.Actual VisualizationYou can view the full version of this step with the branch namestep2.First, you need to add a dependency inCMakeLists.txtandpackage.xmlon the packagerviz_rendering.We need to add three lines to the header file:#include- There’slots of options in the rviz_rendering packagefor objects to build your visualization on. Here we’re using a simple shape.In the class, we’ll add a newprotectedvirtual method:voidonInitialize()override;We also add a pointer to our shape object:std::unique_ptrpoint_shape_;Then in the cpp file, we define theonInitializemethod:voidPointDisplay::onInitialize(){MFDClass::onInitialize();point_shape_=std::make_unique(rviz_rendering::Shape::Type::Cube,scene_manager_,scene_node_);}MFDClassisaliasedto the templated parent class for convenience.The shape object must be constructed here in theonInitializemethod rather than the constructor because otherwisescene_manager_andscene_node_would not be ready.We also update ourprocessMessagemethod:voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<header.frame_id);Ogre::Vector3position;Ogre::Quaternionorientation;if(!context_->getFrameManager()->getTransform(msg->header,position,orientation)){RVIZ_COMMON_LOG_DEBUG_STREAM("Error transforming from frame '"<header.frame_id<<"' to frame '"<setPosition(position);scene_node_->setOrientation(orientation);Ogre::Vector3point_pos;point_pos.x=msg->x;point_pos.y=msg->y;point_shape_->setPosition(point_pos);}We need to get the proper frame for our message and transform thescene_node_accordingly. +This ensures that the visualization does not always appear relative to the fixed frame.The actual visualization that we’ve been building up to is in the last four lines: we set the position of the visualization to match the message’s position.The result should look like this:If the box does not appear in that location, it might be because:You are not publishing the topic at this timeThe message hasn’t been published in the last 2 seconds.You did not properly set the topic in RViz.It’s Nice to Have Options.If you want to allow users to customize different properties of the visualization, you need to addrviz_common::Property objects.You can view the full version of this step with the branch namestep3.Header UpdatesInclude the header file for color properties:#include. +Color is but one of many properties you can set.Add in the prototype forupdateStyle, which is called whenever the GUI is changed via Qt’s SIGNAL/SLOT framework:privateQ_SLOTS:voidupdateStyle();Add in a new property to store the property itself:std::unique_ptrcolor_property_;Cpp Updates#include- Contains helper function to convert property to OGRE color.To ouronInitializewe addcolor_property_=std::make_unique("Point Color",QColor(36,64,142),"Color to draw the point.",this,SLOT(updateStyle()));updateStyle();This constructs the object with its name, default value, description and the callback.We callupdateStyledirectly so that the color is set at the beginning even before the property is changed.Then we define the callback.voidPointDisplay::updateStyle(){Ogre::ColourValuecolor=rviz_common::properties::qtToOgre(color_property_->getColor());point_shape_->setColor(color);}The result should look like this:Ooh, pink!Status ReportYou can view the full version of this step with the branch namestep4.You can also set the status of the display. +As an arbitrary example, let’s make our display show a warning when the x coordinate is negative, because why not? +InprocessMessage:if(msg->x<0){setStatus(StatusProperty::Warn,"Message","I will complain about points with negative x values.");}else{setStatus(StatusProperty::Ok,"Message","OK");}We’re assuming a previoususingrviz_common::properties::StatusProperty;declaration.Think of the status as Key/Value pairs, with the key being some string (here we’re using"Message") and the values are the status level (error/warn/ok) and the description (some other string).CleanupNow its time to clean it up a bit. +This makes things look nicer and be a little easier to use, but aren’t strictly required. +You can view the full version of this step with the branch namestep5.First, we update the plugin declaration.Tutorialtodisplayapointrviz_plugin_tutorial_msgs/msg/Point2DWe add thenamefield to theclasstag. +This changes the name that is displayed in RViz. +In code, it makes sense to call it aPointDisplaybut in RViz, we want to simplify.We put actual text into the description. Don’t be lazy.By declaring the specific message type here, when you attempt to add a Display by Topic, it will suggest this plugin for the topics of that type.We also add an icon for the plugin aticons/classes/Point2D.png. +The folder is hardcoded, and the filename should match the name from the plugin declaration (or the name of the class if not specified).[icon source]We need to install the image file in the CMake.install(FILESicons/classes/Point2D.pngDESTINATIONshare/${PROJECT_NAME}/icons/classes)Now when you add the display, it should show up with an icon and description.Here is the display when attempting to add by topic:And finally, here’s the icon in the standard interface:Note, if you change the plugins name, previous RViz configurations will no longer work. + +Code Examples: + +Language: unknown +std_msgs/Headerheaderfloat64xfloat64y + +Language: unknown +#ifndef RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#define RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_#include#includenamespacerviz_plugin_tutorial{classPointDisplay:publicrviz_common::MessageFilterDisplay{Q_OBJECTprotected:voidprocessMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg)override;};}// namespace rviz_plugin_tutorial#endif// RVIZ_PLUGIN_TUTORIAL__POINT_DISPLAY_HPP_ + +Language: unknown +#include#includenamespacerviz_plugin_tutorial{voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<header.frame_id);}}// namespace rviz_plugin_tutorial#includePLUGINLIB_EXPORT_CLASS(rviz_plugin_tutorial::PointDisplay,rviz_common::Display) + +Language: unknown +pluginlibrviz_commonrviz_plugin_tutorial_msgs + +Language: unknown + + +Language: unknown +find_package(ament_cmake_rosREQUIRED)find_package(pluginlibREQUIRED)find_package(rviz_commonREQUIRED)find_package(rviz_plugin_tutorial_msgsREQUIRED)set(CMAKE_AUTOMOCON)qt5_wrap_cpp(MOC_FILESinclude/rviz_plugin_tutorial/point_display.hpp)add_library(point_displaysrc/point_display.cpp${MOC_FILES})target_include_directories(point_displayPUBLIC$$)ament_target_dependencies(point_displaypluginlibrviz_commonrviz_plugin_tutorial_msgs)install(TARGETSpoint_displayEXPORTexport_rviz_plugin_tutorialARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)install(DIRECTORYinclude/DESTINATIONinclude)install(FILESrviz_common_plugins.xmlDESTINATIONshare/${PROJECT_NAME})ament_export_include_directories(include)ament_export_targets(export_rviz_plugin_tutorial)pluginlib_export_plugin_description_file(rviz_commonrviz_common_plugins.xml) + +Language: unknown +[rviz2]: PluginlibFactory: The plugin for class 'rviz_plugin_tutorial::PointDisplay' failed to load. Error: Failed to load library /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so. Make sure that you are calling the PLUGINLIB_EXPORT_CLASS macro in the library code, and that names are consistent between this macro and your XML. Error string: Could not load library LoadLibrary error: /home/ros/ros2_ws/install/rviz_plugin_tutorial/lib/libpoint_display.so: undefined symbol: _ZTVN20rviz_plugin_tutorial12PointDisplayE, at /tmp/binarydeb/ros-foxy-rcutils-1.1.4/src/shared_library.c:84 + +Language: unknown +ros2topicpub/pointrviz_plugin_tutorial_msgs/msg/Point2D"{header: {frame_id: map}, x: 1, y: 2}"-r0.5 + +Language: unknown +voidPointDisplay::onInitialize(){MFDClass::onInitialize();point_shape_=std::make_unique(rviz_rendering::Shape::Type::Cube,scene_manager_,scene_node_);} + +Language: unknown +voidPointDisplay::processMessage(constrviz_plugin_tutorial_msgs::msg::Point2D::ConstSharedPtrmsg){RVIZ_COMMON_LOG_INFO_STREAM("We got a message with frame "<header.frame_id);Ogre::Vector3position;Ogre::Quaternionorientation;if(!context_->getFrameManager()->getTransform(msg->header,position,orientation)){RVIZ_COMMON_LOG_DEBUG_STREAM("Error transforming from frame '"<header.frame_id<<"' to frame '"<setPosition(position);scene_node_->setOrientation(orientation);Ogre::Vector3point_pos;point_pos.x=msg->x;point_pos.y=msg->y;point_shape_->setPosition(point_pos);} + +Language: unknown +privateQ_SLOTS:voidupdateStyle(); + +Language: unknown +color_property_=std::make_unique("Point Color",QColor(36,64,142),"Color to draw the point.",this,SLOT(updateStyle()));updateStyle(); + +Language: unknown +voidPointDisplay::updateStyle(){Ogre::ColourValuecolor=rviz_common::properties::qtToOgre(color_property_->getColor());point_shape_->setColor(color);} + +Language: unknown +if(msg->x<0){setStatus(StatusProperty::Warn,"Message","I will complain about points with negative x values.");}else{setStatus(StatusProperty::Ok,"Message","OK");} + +Language: unknown +Tutorialtodisplayapointrviz_plugin_tutorial_msgs/msg/Point2D + +Language: unknown +install(FILESicons/classes/Point2D.pngDESTINATIONshare/${PROJECT_NAME}/icons/classes) diff --git "a/exported_docs/ros2/Building_a_custom_deb_package\357\203\201.txt" "b/exported_docs/ros2/Building_a_custom_deb_package\357\203\201.txt" new file mode 100644 index 0000000..4df27b0 --- /dev/null +++ "b/exported_docs/ros2/Building_a_custom_deb_package\357\203\201.txt" @@ -0,0 +1,23 @@ +Title: Building a custom deb package +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Building-a-Custom-Deb-Package.html +Section: Installation +-------------------------------------------------------------------------------- + +Building a custom deb packageMany Ubuntu users install ROS 2 on their system by installingdeb packages. +This guide gives a short set of instructions to build local, custom deb packages.Table of ContentsPrerequisitesInstall dependenciesInitialize rosdepBuild the deb from the packagePrerequisitesTo successfully build a custom package, all of the dependencies of the package to be built must be available locally or in rosdep. +Additionally, all of the dependencies of the package should be properly declared in thepackage.xmlfile of the package.Install dependenciesRun the following command to install utilities needed for the build:$sudoaptinstallpython3-bloompython3-rosdepfakerootdebhelperdh-pythonInitialize rosdepInitialize the rosdep database by calling:$sudorosdepinit +$rosdepupdateNote that therosdepinitcommand may fail if it has already been initialized in the past; this can safely be ignored.Build the deb from the packageRun the following commands to build the deb:$cd/path/to/pkg_source# this should be the directory that contains the package.xml$bloom-generaterosdebian +$fakerootdebian/rulesbinaryAssuming that all required dependencies are available and that compilation succeeds, the new package will be available in the parent directory of this directory. + +Code Examples: + +Language: unknown +$sudoaptinstallpython3-bloompython3-rosdepfakerootdebhelperdh-python + +Language: unknown +$sudorosdepinit +$rosdepupdate + +Language: unknown +$cd/path/to/pkg_source# this should be the directory that contains the package.xml$bloom-generaterosdebian +$fakerootdebian/rulesbinary diff --git "a/exported_docs/ros2/Building_a_movable_robot_model\357\203\201.txt" "b/exported_docs/ros2/Building_a_movable_robot_model\357\203\201.txt" new file mode 100644 index 0000000..c37dd7e --- /dev/null +++ "b/exported_docs/ros2/Building_a_movable_robot_model\357\203\201.txt" @@ -0,0 +1,40 @@ +Title: Building a movable robot model +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/URDF/Building-a-Movable-Robot-Model-with-URDF.html +Section: Installation +-------------------------------------------------------------------------------- + +Building a movable robot modelGoal:Learn how to define movable joints in URDF.Tutorial level:IntermediateTime:10 minutesContentsThe HeadThe GripperThe Gripper ArmOther Types of JointsSpecifying the PoseNext stepsIn this tutorial, we’re going to revise the R2D2 model we made in theprevious tutorialso that it has movable joints. +In the previous model, all of the joints were fixed. +Now we’ll explore three other important types of joints: continuous, revolute and prismatic.Make sure you have installed all prerequisites before continuing. +See theprevious tutorialfor information on what is required.Again, all of the robot models mentioned in this tutorial can be found in theurdf_tutorialpackage.Here is the new urdfwith flexible joints. +You can compare it to the previous version to see everything that has changed, but we’re just going to focus on three example joints.To visualize and control this model, run the same command as the last tutorial:ros2 launch urdf_tutorial display.launch.py model:=urdf/06-flexible.urdfHowever now this will also pop up a GUI that allows you to control the values of all the non-fixed joints. +Play with the model some and see how it moves. +Then, we can take a look at how we accomplished this.The HeadThe connection between the body and the head is a continuous joint, meaning that it can take on any angle from negative infinity to positive infinity. +The wheels are also modeled like this, so that they can roll in both directions forever.The only additional information we have to add is the axis of rotation, here specified by an xyz triplet, which specifies a vector around which the head will rotate. +Since we want it to go around the z axis, we specify the vector “0 0 1”.The GripperBoth the right and the left gripper joints are modeled as revolute joints. +This means that they rotate in the same way that the continuous joints do, but they have strict limits. +Hence, we must include the limit tag specifying the upper and lower limits of the joint (in radians). +We also must specify a maximum velocity and effort for this joint but the actual values don’t matter for our purposes here.The Gripper ArmThe gripper arm is a different kind of joint, namely a prismatic joint. +This means that it moves along an axis, not around it. +This translational movement is what allows our robot model to extend and retract its gripper arm.The limits of the prismatic arm are specified in the same way as a revolute joint, except that the units are meters, not radians.Other Types of JointsThere are two other kinds of joints that move around in space. +Whereas the prismatic joint can only move along one dimension, a planar joint can move around in a plane, or two dimensions. +Furthermore, a floating joint is unconstrained, and can move around in any of the three dimensions. +These joints cannot be specified by just one number, and therefore aren’t included in this tutorial.Specifying the PoseAs you move the sliders around in the GUI, the model moves in Rviz. +How is this done? First theGUIparses the URDF and finds all the non-fixed joints and their limits. +Then, it uses the values of the sliders to publishsensor_msgs/msg/JointStatemessages. +Those are then used byrobot_state_publisherto calculate all of transforms between the different parts. +The resulting transform tree is then used to display all of the shapes in Rviz.Next stepsNow that you have a visibly functional model, you canadd in some physical properties, orstart using xacro to simplify your code. + +Code Examples: + +Language: unknown +ros2 launch urdf_tutorial display.launch.py model:=urdf/06-flexible.urdf + +Language: unknown + + +Language: unknown + + +Language: unknown + diff --git "a/exported_docs/ros2/Building_a_real-time_Linux_kernel_[community-contributed]\357\203\201.txt" "b/exported_docs/ros2/Building_a_real-time_Linux_kernel_[community-contributed]\357\203\201.txt" new file mode 100644 index 0000000..ee07830 --- /dev/null +++ "b/exported_docs/ros2/Building_a_real-time_Linux_kernel_[community-contributed]\357\203\201.txt" @@ -0,0 +1,71 @@ +Title: Building a real-time Linux kernel [community-contributed] +URL: https://docs.ros.org/en/jazzy/Tutorials/Miscellaneous/Building-Realtime-rt_preempt-kernel-for-ROS-2.html +Section: Installation +-------------------------------------------------------------------------------- + +Building a real-time Linux kernel [community-contributed]This tutorial begins with a clean Ubuntu 20.04.1 install on Intel x86_64. Actual kernel is 5.4.0-54-generic, but we will install the Latest Stable RT_PREEMPT Version. To build the kernel you need at least 30GB free disk space.Checkhttps://wiki.linuxfoundation.org/realtime/startfor the latest stable version, at the time of writing this is “Latest Stable Version 5.4-rt”. +If we click on thelink, we get the exact version. +Currently it is patch-5.4.78-rt44.patch.gz.We create a directory in our home dir withmkdir~/kerneland switch into it withcd~/kernelWe can go with a browser tohttps://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/and see if the version is there. You can download it from the site and move it manually from /Downloads to the /kernel folder, or download it using wget by right clicking the link using “copy link location”. Example:wgethttps://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.78.tar.gzunpack it withtar-xzflinux-5.4.78.tar.gzdownload rt_preempt patch matching the Kernel version we just downloaded over athttp://cdn.kernel.org/pub/linux/kernel/projects/rt/5.4/wgethttp://cdn.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patch-5.4.78-rt44.patch.gzunpack it withgunzippatch-5.4.78-rt44.patch.gzThen switch into the linux directory withcdlinux-5.4.78/and patch the kernel with the realtime patchpatch-p1<../patch-5.4.78-rt44.patchWe simply want to use the config of our Ubuntu installation, so we get the Ubuntu config withcp/boot/config-5.4.0-54-generic.configOpen Software & Updates. in the Ubuntu Software menu tick the ‘Source code’ boxWe need some tools to build kernel, install them withsudoapt-getbuild-deplinux +sudoapt-getinstalllibncurses-devflexbisonopenssllibssl-devdkmslibelf-devlibudev-devlibpci-devlibiberty-devautoconffakerootTo enable all Ubuntu configurations, we simply useyes''|makeoldconfigThen we need to enable rt_preempt in the kernel. We callmakemenuconfigand set the following# Enable CONFIG_PREEMPT_RT->GeneralSetup->PreemptionModel(FullyPreemptibleKernel(Real-Time))(X)FullyPreemptibleKernel(Real-Time)# Enable CONFIG_HIGH_RES_TIMERS->Generalsetup->Timerssubsystem[*]HighResolutionTimerSupport# Enable CONFIG_NO_HZ_FULL->Generalsetup->Timerssubsystem->Timertickhandling(Fulldyntickssystem(tickless))(X)Fulldyntickssystem(tickless)# Set CONFIG_HZ_1000 (note: this is no longer in the General Setup menu, go back twice)->Processortypeandfeatures->Timerfrequency(1000HZ)(X)1000HZ# Set CPU_FREQ_DEFAULT_GOV_PERFORMANCE [=y]->PowermanagementandACPIoptions->CPUFrequencyscaling->CPUFrequencyscaling(CPU_FREQ[=y])->DefaultCPUFreqgovernor([=y])(X)performanceSave and exit menuconfig. Now we’re going to build the kernel which will take quite some time. (10-30min on a modern cpu)make-j`nproc`deb-pkgAfter the build is finished check the deb packagesls../*deb +../linux-headers-5.4.78-rt41_5.4.78-rt44-1_amd64.deb../linux-image-5.4.78-rt44-dbg_5.4.78-rt44-1_amd64.deb +../linux-image-5.4.78-rt41_5.4.78-rt44-1_amd64.deb../linux-libc-dev_5.4.78-rt44-1_amd64.debThen we install all kernel deb packagessudodpkg-i../*.debNow the real time kernel should be installed. Reboot the system and check the new kernel versionsudoreboot +uname-a +Linuxros2host5.4.78-rt44#1 SMP PREEMPT_RT Fri Nov 6 10:37:59 CET 2020 x86_64 xx + +Code Examples: + +Language: unknown +mkdir~/kernel + +Language: unknown +cd~/kernel + +Language: unknown +wgethttps://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.78.tar.gz + +Language: unknown +tar-xzflinux-5.4.78.tar.gz + +Language: unknown +wgethttp://cdn.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patch-5.4.78-rt44.patch.gz + +Language: unknown +gunzippatch-5.4.78-rt44.patch.gz + +Language: unknown +cdlinux-5.4.78/ + +Language: unknown +patch-p1<../patch-5.4.78-rt44.patch + +Language: unknown +cp/boot/config-5.4.0-54-generic.config + +Language: unknown +sudoapt-getbuild-deplinux +sudoapt-getinstalllibncurses-devflexbisonopenssllibssl-devdkmslibelf-devlibudev-devlibpci-devlibiberty-devautoconffakeroot + +Language: unknown +yes''|makeoldconfig + +Language: unknown +makemenuconfig + +Language: unknown +# Enable CONFIG_PREEMPT_RT->GeneralSetup->PreemptionModel(FullyPreemptibleKernel(Real-Time))(X)FullyPreemptibleKernel(Real-Time)# Enable CONFIG_HIGH_RES_TIMERS->Generalsetup->Timerssubsystem[*]HighResolutionTimerSupport# Enable CONFIG_NO_HZ_FULL->Generalsetup->Timerssubsystem->Timertickhandling(Fulldyntickssystem(tickless))(X)Fulldyntickssystem(tickless)# Set CONFIG_HZ_1000 (note: this is no longer in the General Setup menu, go back twice)->Processortypeandfeatures->Timerfrequency(1000HZ)(X)1000HZ# Set CPU_FREQ_DEFAULT_GOV_PERFORMANCE [=y]->PowermanagementandACPIoptions->CPUFrequencyscaling->CPUFrequencyscaling(CPU_FREQ[=y])->DefaultCPUFreqgovernor([=y])(X)performance + +Language: unknown +make-j`nproc`deb-pkg + +Language: unknown +ls../*deb +../linux-headers-5.4.78-rt41_5.4.78-rt44-1_amd64.deb../linux-image-5.4.78-rt44-dbg_5.4.78-rt44-1_amd64.deb +../linux-image-5.4.78-rt41_5.4.78-rt44-1_amd64.deb../linux-libc-dev_5.4.78-rt44-1_amd64.deb + +Language: unknown +sudodpkg-i../*.deb + +Language: unknown +sudoreboot +uname-a +Linuxros2host5.4.78-rt44#1 SMP PREEMPT_RT Fri Nov 6 10:37:59 CET 2020 x86_64 xx diff --git "a/exported_docs/ros2/Building_a_visual_robot_model_from_scratch\357\203\201.txt" "b/exported_docs/ros2/Building_a_visual_robot_model_from_scratch\357\203\201.txt" new file mode 100644 index 0000000..308c76d --- /dev/null +++ "b/exported_docs/ros2/Building_a_visual_robot_model_from_scratch\357\203\201.txt" @@ -0,0 +1,88 @@ +Title: Building a visual robot model from scratch +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/URDF/Building-a-Visual-Robot-Model-with-URDF-from-Scratch.html +Section: Installation +-------------------------------------------------------------------------------- + +Building a visual robot model from scratchGoal:Learn how to build a visual model of a robot that you can view in RvizTutorial level:IntermediateTime:20 minutesContentsOne ShapeMultiple ShapesOriginsMaterial GirlFinishing the ModelNoteThis tutorial assumes you know how to write well-formatted XML codeIn this tutorial, we’re going to build a visual model of a robot that vaguely looks like R2D2. +In later tutorials, you’ll learn how toarticulate the model,add in some physical properties, andgenerate neater code with xacro, but for now, we’re going to focus on getting the visual geometry correct.Before continuing, make sure you have thejoint_state_publisherpackage installed. +If you installedurdf_tutorialbinaries, this should already be the case. +If not, please update your installation to include that package (userosdepto check).All of the robot models mentioned in this tutorial (and the source files) can be found in theurdf_tutorialpackage.One ShapeFirst, we’re just going to explore one simple shape. +Here’s about as simple as a urdf as you can make.[Source: 01-myfirst.urdf]To translate the XML into English, this is a robot with the namemyfirst, that contains only one link (a.k.a. part), whose visual component is just a cylinder 0.6 meters long with a 0.2 meter radius. +This may seem like a lot of enclosing tags for a simple “hello world” type example, but it will get more complicated, trust me.To examine the model, launch thedisplay.launch.pyfile:ros2 launch urdf_tutorial display.launch.py model:=urdf/01-myfirst.urdfThis does three things:Loads the specified model and saves it as a parameter for therobot_state_publishernode.Runs nodes to publishsensor_msgs/msg/JointStateand transforms (more on these later)Starts Rviz with a configuration fileAfter launchingdisplay.launch.py, you should end up with RViz showing you the following:Things to note:The fixed frame is the transform frame where the center of the grid is located. +Here, it’s a frame defined by our one link, base_link.The visual element (the cylinder) has its origin at the center of its geometry as a default. +Hence, half the cylinder is below the grid.Multiple ShapesNow let’s look at how to add multiple shapes/links. +If we just add more link elements to the urdf, the parser won’t know where to put them. +So, we have to add joints. +Joint elements can refer to both flexible and inflexible joints. +We’ll start with inflexible, or fixed joints.[Source: 02-multipleshapes.urdf]Note how we defined a 0.6m x 0.1m x 0.2m boxThe joint is defined in terms of a parent and a child. +URDF is ultimately a tree structure with one root link. +This means that the leg’s position is dependent on the base_link’s position.ros2 launch urdf_tutorial display.launch.py model:=urdf/02-multipleshapes.urdfBoth of the shapes overlap with each other, because they share the same origin. +If we want them not to overlap we must define more origins.OriginsR2D2’s leg attaches to the top half of his torso, on the side. +So that’s where we specify the origin of the JOINT to be. +Also, it doesn’t attach to the middle of the leg, it attaches to the upper part, so we must offset the origin for the leg as well. +We also rotate the leg so it is upright.[Source: 03-origins.urdf]Let’s start by examining the joint’s origin. +It is defined in terms of the parent’s reference frame. +So we are -0.22 meters in the y direction (to our left, but to the right relative to the axes) and 0.25 meters in the z direction (up). +This means that the origin for the child link will be up and to the right, regardless of the child link’s visual origin tag. +Since we didn’t specify a rpy (roll pitch yaw) attribute, the child frame will be default have the same orientation as the parent frame.Now, looking at the leg’s visual origin, it has both a xyz and rpy offset. +This defines where the center of the visual element should be, relative to its origin. +Since we want the leg to attach at the top, we offset the origin down by setting the z offset to be -0.3 meters. +And since we want the long part of the leg to be parallel to the z axis, we rotate the visual part PI/2 around the Y axis.ros2 launch urdf_tutorial display.launch.py model:=urdf/03-origins.urdfThe launch file runs packages that will create TF frames for each link in your model based on your URDF. +Rviz uses this information to figure out where to display each shape.If a TF frame does not exist for a given URDF link, then it will be placed at the origin in white (ref.related question).Material Girl“Alright,” I hear you say. +“That’s very cute, but not everyone owns a B21. +My robot and R2D2 are not red!” +That’s a good point. +Let’s take a look at the material tag.[Source: 04-materials.urdf]The body is now blue. +We’ve defined a new material called “blue”, with the red, green, blue and alpha channels defined as 0,0,0.8 and 1 respectively. +All of the values can be in the range [0,1]. +This material is then referenced by the base_link’s visual element. +The white material is defined similarly.You could also define the material tag from within the visual element, and even reference it in other links. +No one will even complain if you redefine it though.You can also use a texture to specify an image file to be used for coloring the objectros2 launch urdf_tutorial display.launch.py model:=urdf/04-materials.urdfFinishing the ModelNow we finish the model off with a few more shapes: feet, wheels, and head. +Most notably, we add a sphere and a some meshes. +We’ll also add few other pieces that we’ll use later.[Source: 05-visual.urdf]ros2 launch urdf_tutorial display.launch.py model:=urdf/05-visual.urdfHow to add the sphere should be fairly self explanatory:The meshes here were borrowed from the PR2. +They are separate files which you have to specify the path for. +You should use thepackage://NAME_OF_PACKAGE/pathnotation. +The meshes for this tutorial are located within theurdf_tutorialpackage, in a folder called meshes.The meshes can be imported in a number of different formats. +STL is fairly common, but the engine also supports DAE, which can have its own color data, meaning you don’t have to specify the color/material. +Often these are in separate files. +These meshes reference the.tiffiles also in the meshes folder.Meshes can also be sized using relative scaling parameters or a bounding box size.We could have also referred to meshes in a completely different package.There you have it. +A R2D2-like URDF model. +Now you can continue on to the next step,making it move. + +Code Examples: + +Language: unknown + + +Language: unknown +ros2 launch urdf_tutorial display.launch.py model:=urdf/01-myfirst.urdf + +Language: unknown + + +Language: unknown +ros2 launch urdf_tutorial display.launch.py model:=urdf/02-multipleshapes.urdf + +Language: unknown + + +Language: unknown +ros2 launch urdf_tutorial display.launch.py model:=urdf/03-origins.urdf + +Language: unknown + + +Language: unknown +ros2 launch urdf_tutorial display.launch.py model:=urdf/04-materials.urdf + +Language: unknown + + +Language: unknown +ros2 launch urdf_tutorial display.launch.py model:=urdf/05-visual.urdf + +Language: unknown + + +Language: unknown + diff --git "a/exported_docs/ros2/Citations\357\203\201.txt" "b/exported_docs/ros2/Citations\357\203\201.txt" new file mode 100644 index 0000000..f3a6d48 --- /dev/null +++ "b/exported_docs/ros2/Citations\357\203\201.txt" @@ -0,0 +1,14 @@ +Title: Citations +URL: https://docs.ros.org/en/jazzy/Citations.html +Section: Installation +-------------------------------------------------------------------------------- + +CitationsIf you use ROS 2 in your work please cite the 2022 Science Robotics paperRobot Operating System 2: Design, architecture, and uses in the wild.S. Macenski, T. Foote, B. Gerkey, C. Lalancette, W. Woodall, “Robot Operating System 2: Design, architecture, and uses in the wild,” Science Robotics vol. 7, May 2022.@article{doi:10.1126/scirobotics.abm6074,author={Steven Macenski and Tully Foote and Brian Gerkey and Chris Lalancette and William Woodall},title={Robot Operating System 2: Design, architecture, and uses in the wild},journal={Science Robotics},volume={7},number={66},pages={eabm6074},year={2022},doi={10.1126/scirobotics.abm6074},URL={https://www.science.org/doi/abs/10.1126/scirobotics.abm6074}}If you use ROS 2 Composition in your work, please cite the 2023 IEEE RA-L paperImpact of ROS 2 Node Composition in Robotic Systems.S. Macenski, A. Soragna, M. Carroll, Z. Ge, “Impact of ROS 2 Node Composition in Robotic Systems”, IEEE Robotics and Autonomous Letters (RA-L), 2023.@article{doi:10.48550/arXiv.2305.09933,author={Steven Macenski and Alberto Soragna and Michael Carroll and Zhenpeng Ge},title={Impact of ROS 2 Node Composition in Robotic Systems},journal={IEEE Robotics and Autonomous Letters (RA-L)},year={2023},doi={10.48550/arXiv.2305.09933},URL={https://arxiv.org/abs/2305.09933}} + +Code Examples: + +Language: unknown +@article{doi:10.1126/scirobotics.abm6074,author={Steven Macenski and Tully Foote and Brian Gerkey and Chris Lalancette and William Woodall},title={Robot Operating System 2: Design, architecture, and uses in the wild},journal={Science Robotics},volume={7},number={66},pages={eabm6074},year={2022},doi={10.1126/scirobotics.abm6074},URL={https://www.science.org/doi/abs/10.1126/scirobotics.abm6074}} + +Language: unknown +@article{doi:10.48550/arXiv.2305.09933,author={Steven Macenski and Alberto Soragna and Michael Carroll and Zhenpeng Ge},title={Impact of ROS 2 Node Composition in Robotic Systems},journal={IEEE Robotics and Autonomous Letters (RA-L)},year={2023},doi={10.48550/arXiv.2305.09933},URL={https://arxiv.org/abs/2305.09933}} diff --git "a/exported_docs/ros2/Code_style_and_language_versions\357\203\201.txt" "b/exported_docs/ros2/Code_style_and_language_versions\357\203\201.txt" new file mode 100644 index 0000000..06e2d59 --- /dev/null +++ "b/exported_docs/ros2/Code_style_and_language_versions\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: Code style and language versions +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Contributing/Code-Style-Language-Versions.html +Section: Installation +-------------------------------------------------------------------------------- + +Code style and language versionsTable of ContentsCStandardStyleC++StandardStylePythonVersionStyleCMakeVersionStyleMarkdown / reStructured Text / docblocksStyleIn order to achieve a consistent looking product we will all follow externally (if possible) defined style guidelines for each language. +For other things like package layout or documentation layout we will need to come up with our own guidelines, drawing on current, popular styles in use now.Additionally, wherever possible, developers should use integrated tools to allow them to check that these guidelines are followed in their editors. +For example, everyone should have a PEP8 checker built into their editor to cut down on review iterations related to style.Also where possible, packages should check style as part of their unit tests to help with the automated detection of style issues (seeament_lint_auto).CStandardWe will target C99.StyleWe will usePython’s PEP7for our C style guide, with some modifications and additions:We will target C99, as we do not need to support C89 (as PEP7 recommends)rationale: among other things it allows us to use both//and/**/style commentsrationale: C99 is pretty much ubiquitous nowC++ style//comments are allowed(optional) Always place literals on the left-hand side of comparison operators, e.g.0==retinstead ofret==0rationale:ret==0too easily turns intoret=0by accidentoptional because when using-Wall(or equivalent) modern compilers will warn you when this happensAll of the following modifications only apply if we are not writing Python modules:Do not usePy_as a prefix for everythinginstead use a CamelCase version of the package name or other appropriate prefixThe stuff about documentation strings doesn’t applyWe can use thepep7python module for style checking. The editor integration seems slim, we may need to look into automated checking for C in more detail.C++StandardJazzy targets C++17.StyleWe will use theGoogle C++ Style Guide, with some modifications:Line LengthOur maximum line length is 100 characters.File ExtensionsHeader files should use the .hpp extension.rationale: Allow tools to determine content of files, C++ or C.Implementation files should use the .cpp extension.rationale: Allow tools to determine content of files, C++ or C.Variable NamingFor global variables use lowercase with underscores prefixed withg_rationale: keep variable naming case consistent across the projectrationale: easy to tell the scope of a variable at a glanceconsistency across languagesFunction and Method NamingGoogle style guide saysCamelCase, but the C++ std library’s style ofsnake_caseis also allowedrationale: ROS 2 core packages currently usesnake_casereason: either an historical oversight or a personal preference that didn’t get checked by the linterreason for not changing: retroactively changing would be too disruptiveother considerations:cpplint.pydoes not check this case (hard to enforce other than with review)snake_casecan result in more consistency across languagesspecific guidance:for existing projects, prefer the existing stylefor new projects, either is acceptable, but a preference for matching related existing projects is advisedfinal decision is always developer discretionspecial cases like function pointers, callable types, etc. may require bending the rulesNote that classes should still useCamelCaseby defaultAccess ControlDrop requirement for all class members to be private and therefore require accessorsrationale: this is overly constraining for user API designwe should prefer private members, only making them public when they are neededwe should consider using accessors before choosing to allow direct member accesswe should have a good reason for allowing direct member access, other than because it is convenient for usExceptionsExceptions are allowedrationale: this is a new codebase, so the legacy argument doesn’t apply to usrationale: for user-facing API’s it is more idiomatic C++ to have exceptionsExceptions in destructors should be explicitly avoidedWe should consider avoiding Exceptions if we intend to wrap the resulting API in Crationale: it will make it easier to wrap in Crationale: most of our dependencies in code we intend to wrap in C do not use exceptions anywaysFunction-like ObjectsNo restrictions on Lambda’s orstd::functionorstd::bindBoostBoost should be avoided unless absolutely required.Comments and Doc CommentsUse///and/***/comments fordocumentationpurposes and//style comments for notes and general commentsClass and Function comments should use///and/***/style commentsrationale: these are recommended for Doxygen and Sphinx in C/C++rationale: mixing/**/and//is convenient for block commenting out code which contains commentsDescriptions of how the code works or notes within classes and functions should use//style commentsPointer Syntax AlignmentUsechar*c;instead ofchar*c;orchar*c;because of this scenariochar*c,*d,*e;Class Privacy KeywordsDo not put 1 space beforepublic:,private:, orprotected:, it is more consistent for all indentions to be a multiple of 2rationale: most editors don’t like indentions which are not a multiple of the (soft) tab sizeUse zero spaces beforepublic:,private:, orprotected:, or 2 spacesIf you use 2 spaces before, indent other class statements by 2 additional spacesPrefer zero spaces, i.e.public:,private:, orprotected:in the same column as the classNested TemplatesNever add whitespace to nested templatesPreferset>(C++11 feature) toset>orset>Always Use BracesAlways use braces followingif,else,do,while, andfor, even when the body is a single line.rationale: less opportunity for visual ambiguity and for complications due to use of macros in the bodyOpen Versus Cuddled BracesUse open braces forfunction,class,enum, andstructdefinitions, but cuddle braces onif,else,while,for, etc…Exception: when anif(orwhile, etc.) condition is long enough to require line-wrapping, then use an open brace (i.e., don’t cuddle).When a function call cannot fit on one line, wrap at the open parenthesis (not in between arguments) and start them on the next line with a 2-space indent. Continue with the 2-space indent on subsequent lines for more arguments. (Note that theGoogle style guideis internally contradictory on this point.)Same goes forif(andwhile, etc.) conditions that are too long to fit on one line.ExamplesThis is OK:intmain(intargc,char**argv){if(condition){return0;}else{return1;}}if(this&&that||both){...}// Long condition; open braceif(this&&that||both&&this&&that||both&&this&&that||both&&this&&that){...}// Short function callcall_func(foo,bar);// Long function call; wrap at the open parenthesiscall_func(foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar);// Very long function argument; separate it for readabilitycall_func(bang,fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo,bar,bat);This isnotOK:intmain(intargc,char**argv){return0;}if(this&&that||both){...}Use open braces rather than excessive indention, e.g. for distinguishing constructor code from constructor initializer listsThis is OK:ReturnTypeLongClassName::ReallyReallyReallyLongFunctionName(Typepar_name1,// 2 space indentTypepar_name2,Typepar_name3){DoSomething();// 2 space indent...}MyClass::MyClass(intvar):some_var_(var),some_other_var_(var+1){...DoSomething();...}This isnotOK, even weird (the google way?):ReturnTypeLongClassName::ReallyReallyReallyLongFunctionName(Typepar_name1,// 4 space indentTypepar_name2,Typepar_name3){DoSomething();// 2 space indent...}MyClass::MyClass(intvar):some_var_(var),// 4 space indentsome_other_var_(var+1){// lined up...DoSomething();...}LintersWe check these styles with a combination of Google’scpplint.pyanduncrustify.We provide command line tools with custom configurations:ament_clang_format:configurationament_cpplintament_uncrustify:configurationSome formatters such as ament_uncrustify and ament_clang_format support--reformatoptions to apply changes in place.We also run other tools to detect and eliminate as many warnings as possible. +Here’s a non-exhaustive list of additional things we try to do on all of our packages:use compiler flags like-Wall-Wextra-Wpedanticrun static code analysis likecppcheck, which we have integrated inament_cppcheck.PythonVersionWe will target Python 3 for our development.StyleWe will use thePEP8 guidelinesfor code format.We chose the following more precise rule where PEP 8 leaves some freedom:We allow up to 100 characters per line (fifth paragraph).We pick single quotes over double quotes as long as no escaping is necessary.We prefer hanging indents for continuation lines.Tools like the(ament_)pycodestylePython package should be used in unit-test and/or editor integration for checking Python code style.The pycodestyle configuration used in the linter ishere.Integration with editors:atom:https://atom.io/packages/linter-pycodestyleemacs:https://www.emacswiki.org/emacs/PythonProgrammingInEmacsSublime Text:https://sublime.wbond.net/packages/SublimeLinter-flake8vim:https://github.com/nvie/vim-flake8CMakeVersionWe will target CMake 3.8.StyleSince there is not an existing CMake style guide we will define our own:Use lowercase command names (find_package, notFIND_PACKAGE).Usesnake_caseidentifiers (variables, functions, macros).Use emptyelse()andend...()commands.No whitespace before(‘s.Use two spaces of indention, do not use tabs.Do not use aligned indentation for parameters of multi-line macro invocations. Use two spaces only.Prefer functions withset(PARENT_SCOPE)to macros.When using macros prefix local variables with_or a reasonable prefix.Markdown / reStructured Text / docblocksStyleThe following rules to format text is intended to increase readability as well as versioning.[.md, .rst only]Each section title should be preceded by one empty line and succeeded by one empty line.Rationale: It expedites to get an overview about the structure when screening the document.[.rst only]In reStructured Text the headings should follow the hierarchy described in theSphinx style guide:#with overline (only once, used for the document title)*with overline=-^"Rationale: A consistent hierarchy expedites getting an idea about the nesting level when screening the document.[.md only]In Markdown the headings should follow the ATX-style described in theMarkdown syntax documentationATX-style headers use 1-6 hash characters (#) at the start of the line to denote header levels 1-6.A space between the hashes and the header title should be used (such as#Heading1) to make it easier to visually separate them.Justification for the ATX-style preference comes from theGoogle Markdown style guideRationale: ATX-style headers are easier to search and maintain, and make the first two header levels consistent with the other levels.[any]Each sentence must start on a new line.Rationale: For longer paragraphs a single change in the beginning makes the diff unreadable since it carries forward through the whole paragraph.[any]Each sentence can optionally be wrapped to keep each line short.[any]The lines should not have any trailing white spaces.[.md, .rst only]A code block must be preceded and succeeded by an empty line.Rationale: Whitespace is significant only directly before and directly after fenced code blocks. +Following these instructions will ensure that highlighting works properly and consistently.[.md, .rst only]A code block should specify a syntax (e.g.bash). + +Code Examples: + +Language: unknown +intmain(intargc,char**argv){if(condition){return0;}else{return1;}}if(this&&that||both){...}// Long condition; open braceif(this&&that||both&&this&&that||both&&this&&that||both&&this&&that){...}// Short function callcall_func(foo,bar);// Long function call; wrap at the open parenthesiscall_func(foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar,foo,bar);// Very long function argument; separate it for readabilitycall_func(bang,fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo,bar,bat); + +Language: unknown +intmain(intargc,char**argv){return0;}if(this&&that||both){...} + +Language: unknown +ReturnTypeLongClassName::ReallyReallyReallyLongFunctionName(Typepar_name1,// 2 space indentTypepar_name2,Typepar_name3){DoSomething();// 2 space indent...}MyClass::MyClass(intvar):some_var_(var),some_other_var_(var+1){...DoSomething();...} + +Language: unknown +ReturnTypeLongClassName::ReallyReallyReallyLongFunctionName(Typepar_name1,// 4 space indentTypepar_name2,Typepar_name3){DoSomething();// 2 space indent...}MyClass::MyClass(intvar):some_var_(var),// 4 space indentsome_other_var_(var+1){// lined up...DoSomething();...} diff --git "a/exported_docs/ros2/Composing_multiple_nodes_in_a_single_process\357\203\201.txt" "b/exported_docs/ros2/Composing_multiple_nodes_in_a_single_process\357\203\201.txt" new file mode 100644 index 0000000..4d01c74 --- /dev/null +++ "b/exported_docs/ros2/Composing_multiple_nodes_in_a_single_process\357\203\201.txt" @@ -0,0 +1,125 @@ +Title: Composing multiple nodes in a single process +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Composition.html +Section: Installation +-------------------------------------------------------------------------------- + +Composing multiple nodes in a single processTable of ContentsBackgroundPrerequisitesRun the demosDiscover available componentsRun-time composition using ROS services with a publisher and subscriberRun-time composition using ROS services with a server and clientCompile-time composition with hardcoded nodesRun-time composition using dlopenComposition using launch actionsAdvanced TopicsUnloading componentsRemapping container name and namespaceRemap component names and namespacesPassing parameter values into componentsPassing additional arguments into componentsComposable nodes as shared librariesComposing Non-Node Derived ComponentsGoal:Compose multiple nodes into a single process.Tutorial level:IntermediateTime:20 minutesBackgroundSee theconceptual article.For information on how to write a composable node,check out this tutorial.PrerequisitesThis tutorial uses executables from therclcpp_components,ros2component,composition, andimage_toolspackages. If you’ve followed theinstallation instructionsfor your platform, these should already be installed.Run the demosDiscover available componentsTo see what components are registered and available in the workspace, execute the following in a shell:ros2componenttypesThe terminal will return the list of all available components:(...componentsofotherpackageshere)compositioncomposition::Talkercomposition::Listenercomposition::NodeLikeListenercomposition::Servercomposition::Client(...componentsofotherpackageshere)Run-time composition using ROS services with a publisher and subscriberIn the first shell, start the component container:ros2runrclcpp_componentscomponent_containerOpen the second shell and verify that the container is running viaros2command line tools:ros2componentlistYou should see a name of the component:/ComponentManagerIn the second shell load the talker component (seetalkersource code):ros2componentload/ComponentManagercompositioncomposition::TalkerThe command will return the unique ID of the loaded component as well as the node name:Loadedcomponent1into'/ComponentManager'containernodeas'/talker'Now the first shell should show a message that the component was loaded as well as repeated message for publishing a message.Run another command in the second shell to load the listener component (seelistenersource code):ros2componentload/ComponentManagercompositioncomposition::ListenerTerminal will return:Loadedcomponent2into'/ComponentManager'containernodeas'/listener'Theros2command line utility can now be used to inspect the state of the container:ros2componentlistYou will see the following result:/ComponentManager1/talker2/listenerNow the first shell should show repeated output for each received message.Run-time composition using ROS services with a server and clientThe example with a server and a client is very similar.In the first shell:ros2runrclcpp_componentscomponent_containerIn the second shell (seeserverandclientsource code):ros2componentload/ComponentManagercompositioncomposition::Server +ros2componentload/ComponentManagercompositioncomposition::ClientIn this case the client sends a request to the server, the server processes the request and replies with a response, and the client prints the received response.Compile-time composition with hardcoded nodesThis demo shows that the same shared libraries can be reused to compile a single executable running multiple components without using ROS interfaces. +The executable contains all four components from above: talker and listener as well as server and client, which is hardcoded in the main function.In the shell call (seesource code):ros2runcompositionmanual_compositionThis should show repeated messages from both pairs, the talker and the listener as well as the server and the client.NoteManually-composed components will not be reflected in theros2componentlistcommand line tool output.Run-time composition using dlopenThis demo presents an alternative to run-time composition by creating a generic container process and explicitly passing the libraries to load without using ROS interfaces. +The process will open each library and create one instance of each “rclcpp::Node” class in the library (source code).LinuxmacOSWindowsros2runcompositiondlopen_composition`ros2pkgprefixcomposition`/lib/libtalker_component.so`ros2pkgprefixcomposition`/lib/liblistener_component.soros2runcompositiondlopen_composition`ros2pkgprefixcomposition`/lib/libtalker_component.dylib`ros2pkgprefixcomposition`/lib/liblistener_component.dylib>ros2pkgprefixcompositionto get the path to where composition is installed. Then call>ros2runcompositiondlopen_composition\bin\talker_component.dll\bin\listener_component.dllNow the shell should show repeated output for each sent and received message.Notedlopen-composed components will not be reflected in theros2componentlistcommand line tool output.Composition using launch actionsWhile the command line tools are useful for debugging and diagnosing component configurations, it is frequently more convenient to start a set of components at the same time. +To automate this action, we can use alaunch file:ros2launchcompositioncomposition_demo_launch.pyAdvanced TopicsNow that we have seen the basic operation of components, we can discuss a few more advanced topics.Unloading componentsIn the first shell, start the component container:ros2runrclcpp_componentscomponent_containerVerify that the container is running viaros2command line tools:ros2componentlistYou should see a name of the component:/ComponentManagerIn the second shell load both the talker and listener as we have before:ros2componentload/ComponentManagercompositioncomposition::Talker +ros2componentload/ComponentManagercompositioncomposition::ListenerUse the unique ID to unload the node from the component container.ros2componentunload/ComponentManager12The terminal should return:Unloadedcomponent1from'/ComponentManager'container +Unloadedcomponent2from'/ComponentManager'containerIn the first shell, verify that the repeated messages from talker and listener have stopped.Remapping container name and namespaceThe component manager name and namespace can be remapped via standard command line arguments:ros2runrclcpp_componentscomponent_container--ros-args-r__node:=MyContainer-r__ns:=/nsIn a second shell, components can be loaded by using the updated container name:ros2componentload/ns/MyContainercompositioncomposition::ListenerNoteNamespace remappings of the container do not affect loaded components.Remap component names and namespacesComponent names and namespaces may be adjusted via arguments to the load command.In the first shell, start the component container:ros2runrclcpp_componentscomponent_containerSome examples of how to remap names and namespaces.Remap node name:ros2componentload/ComponentManagercompositioncomposition::Talker--node-nametalker2Remap namespace:ros2componentload/ComponentManagercompositioncomposition::Talker--node-namespace/nsRemap both:ros2componentload/ComponentManagercompositioncomposition::Talker--node-nametalker3--node-namespace/ns2Now useros2command line utility:ros2componentlistIn the console you should see corresponding entries:/ComponentManager1/talker22/ns/talker3/ns2/talker3NoteNamespace remappings of the container do not affect loaded components.Passing parameter values into componentsTheros2componentloadcommand-line supports passing arbitrary parameters to the node as it is constructed. +This functionality can be used as follows:ros2componentload/ComponentManagerimage_toolsimage_tools::Cam2Image-pburger_mode:=truePassing additional arguments into componentsTheros2componentloadcommand-line supports passing particular options to the component manager for use when constructing the node. +As of now, the only command-line option that is supported is to instantiate a node using intra-process communication. +This functionality can be used as follows:ros2componentload/ComponentManagercompositioncomposition::Talker-euse_intra_process_comms:=trueComposable nodes as shared librariesIf you want to export a composable node as a shared library from a package and use that node in another package that does link-time composition, add code to the CMake file which imports the actual targets in downstream packages.Then install the generated file and export the generated file.A practical example can be seen here:ROS Discourse - Ament best practice for sharing librariesComposing Non-Node Derived ComponentsIn ROS 2, components allow for more efficient use of system resources and provide a powerful feature that enables you to create reusable functionality that is not tied to a specific node.One advantage of using components is that they allow you to create non-node derived functionality as standalone executables or shared libraries that can be loaded into the ROS system as needed.To create a component that is not derived from a node, follow these guidelines:Implement a constructor that takesconstrclcpp::NodeOptions&as its argument.Implement theget_node_base_interface()method, which should return aNodeBaseInterface::SharedPtr. You can use theget_node_base_interface()method of a node that you create in your constructor to provide this interface.Here’s an example of a component that is not derived from a node, which listens to a ROS topic:node_like_listener_component.For more information on this topic, you can refer to thisdiscussion. + +Code Examples: + +Language: unknown +ros2componenttypes + +Language: unknown +(...componentsofotherpackageshere)compositioncomposition::Talkercomposition::Listenercomposition::NodeLikeListenercomposition::Servercomposition::Client(...componentsofotherpackageshere) + +Language: unknown +ros2runrclcpp_componentscomponent_container + +Language: unknown +ros2componentlist + +Language: unknown +/ComponentManager + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker + +Language: unknown +Loadedcomponent1into'/ComponentManager'containernodeas'/talker' + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Listener + +Language: unknown +Loadedcomponent2into'/ComponentManager'containernodeas'/listener' + +Language: unknown +ros2componentlist + +Language: unknown +/ComponentManager1/talker2/listener + +Language: unknown +ros2runrclcpp_componentscomponent_container + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Server +ros2componentload/ComponentManagercompositioncomposition::Client + +Language: unknown +ros2runcompositionmanual_composition + +Language: unknown +ros2runcompositiondlopen_composition`ros2pkgprefixcomposition`/lib/libtalker_component.so`ros2pkgprefixcomposition`/lib/liblistener_component.so + +Language: unknown +ros2runcompositiondlopen_composition`ros2pkgprefixcomposition`/lib/libtalker_component.dylib`ros2pkgprefixcomposition`/lib/liblistener_component.dylib + +Language: unknown +>ros2pkgprefixcomposition + +Language: unknown +>ros2runcompositiondlopen_composition\bin\talker_component.dll\bin\listener_component.dll + +Language: unknown +ros2launchcompositioncomposition_demo_launch.py + +Language: unknown +ros2runrclcpp_componentscomponent_container + +Language: unknown +ros2componentlist + +Language: unknown +/ComponentManager + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker +ros2componentload/ComponentManagercompositioncomposition::Listener + +Language: unknown +ros2componentunload/ComponentManager12 + +Language: unknown +Unloadedcomponent1from'/ComponentManager'container +Unloadedcomponent2from'/ComponentManager'container + +Language: unknown +ros2runrclcpp_componentscomponent_container--ros-args-r__node:=MyContainer-r__ns:=/ns + +Language: unknown +ros2componentload/ns/MyContainercompositioncomposition::Listener + +Language: unknown +ros2runrclcpp_componentscomponent_container + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker--node-nametalker2 + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker--node-namespace/ns + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker--node-nametalker3--node-namespace/ns2 + +Language: unknown +ros2componentlist + +Language: unknown +/ComponentManager1/talker22/ns/talker3/ns2/talker3 + +Language: unknown +ros2componentload/ComponentManagerimage_toolsimage_tools::Cam2Image-pburger_mode:=true + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker-euse_intra_process_comms:=true diff --git "a/exported_docs/ros2/Composition\357\203\201.txt" "b/exported_docs/ros2/Composition\357\203\201.txt" new file mode 100644 index 0000000..a0470b9 --- /dev/null +++ "b/exported_docs/ros2/Composition\357\203\201.txt" @@ -0,0 +1,24 @@ +Title: Composition +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Composition.html +Section: Installation +-------------------------------------------------------------------------------- + +CompositionTable of ContentsROS 1 - Nodes vs. NodeletsROS 2 - Unified APIWriting a ComponentUsing ComponentsPractical applicationROS 1 - Nodes vs. NodeletsIn ROS 1 you can write your code either as aROS nodeor as aROS nodelet. +ROS 1 nodes are compiled into executables. +ROS 1 nodelets on the other hand are compiled into a shared library which is then loaded at runtime by a container process.ROS 2 - Unified APIIn ROS 2 the recommended way of writing your code is similar to a nodelet - we call it aComponent. +This makes it easy to add common concepts to existing code, like alife cycle. +Having different APIs, which was the biggest drawback in ROS 1, is avoided in ROS 2 since both approaches use the same API.NoteIt is still possible to use the node-like style of “writing your own main” but for the common case it is not recommended.By making the process layout a deploy-time decision the user can choose between:running multiple nodes in separate processes with the benefits of process/fault isolation as well as easier debugging of individual nodes andrunning multiple nodes in a single process with the lower overhead and optionally more efficient communication (seeIntra Process Communication).Additionallyros2launchcan be used to automate these actions through specialized launch actions.Writing a ComponentSince a component is only built into a shared library, it doesn’t have amainfunction (seeTalker source code). +A component is commonly a subclass ofrclcpp::Node. +Since it is not in control of the thread, it shouldn’t perform any long running or blocking tasks in its constructor. +Instead, it can use timers to get periodic notifications. +Additionally, it can create publishers, subscriptions, servers, and clients.An important aspect of making such a class a component is that the class registers itself using macros from the packagerclcpp_components(see the last line in the source code). +This makes the component discoverable when its library is being loaded into a running process - it acts as kind of an entry point.Additionally, once a component is created, it must be registered with the index to be discoverable by the tooling.add_library(talker_componentSHAREDsrc/talker_component.cpp)rclcpp_components_register_nodes(talker_component"composition::Talker")# To register multiple components in the same shared library, use multiple calls# rclcpp_components_register_nodes(talker_component "composition::Talker2")For an example,check out this tutorialNoteIn order for the component_container to be able to find desired components, it must be executed or launched from a shell that has sourced the corresponding workspace.Using ComponentsThecompositionpackage contains a couple of different approaches on how to use components. +The three most common ones are:Start a (generic container process) and call the ROS serviceload_nodeoffered by the container. +The ROS service will then load the component specified by the passed package name and library name and start executing it within the running process. +Instead of calling the ROS service programmatically you can also use acommand line toolto invoke the ROS service with the passed command line argumentsCreate acustom executablecontaining multiple nodes which are known at compile time. +This approach requires that each component has a header file (which is not strictly needed for the first case).Create a launch file and useros2launchto create a container process with multiple components loaded.Practical applicationTry theComposition demos. + +Code Examples: + +Language: unknown +add_library(talker_componentSHAREDsrc/talker_component.cpp)rclcpp_components_register_nodes(talker_component"composition::Talker")# To register multiple components in the same shared library, use multiple calls# rclcpp_components_register_nodes(talker_component "composition::Talker2") diff --git a/exported_docs/ros2/Concepts.txt b/exported_docs/ros2/Concepts.txt new file mode 100644 index 0000000..f6c53ca --- /dev/null +++ b/exported_docs/ros2/Concepts.txt @@ -0,0 +1,5 @@ +Title: Concepts +URL: https://docs.ros.org/en/jazzy/Concepts.html +Section: Concepts +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/ros2/Configure_service_introspection\357\203\201.txt" "b/exported_docs/ros2/Configure_service_introspection\357\203\201.txt" new file mode 100644 index 0000000..2d3320b --- /dev/null +++ "b/exported_docs/ros2/Configure_service_introspection\357\203\201.txt" @@ -0,0 +1,45 @@ +Title: Configure service introspection +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos/Service-Introspection.html +Section: Installation +-------------------------------------------------------------------------------- + +Configure service introspectionGoal:Configure service introspection for a service client and a server.Tutorial level:AdvancedTime:15 minutesTable of ContentsOverviewInstalling the demoIntrospection Configuration StateIntrospection demoRelated contentOverviewROS 2 applications usually consist of services to execute specific procedures in remote nodes. +It is possible to introspect service data communication with service introspection.In this demo, we’ll be highlighting how to configure service introspection state for a service client and a server and monitor service communication withros2serviceecho.Installing the demoSee theinstallation instructionsfor details on installing ROS 2.If you’ve installed ROS 2 binary packages, ensure that you haveros-jazzy-demo-nodes-cppinstalled. +If you downloaded the archive or built ROS 2 from source, it will already be part of the installation.Introspection Configuration StateThere are 3 configuration states for service introspection.Service Introspection Configuration StateRCL_SERVICE_INTROSPECTION_OFFDisabledRCL_SERVICE_INTROSPECTION_METADATAOnly metadata without any user data contentsRCL_SERVICE_INTROSPECTION_CONTENTSUser data contents with metadataIntrospection demoThis demo shows how to manage service introspection and monitor the service data communication with usingros2serviceecho.IntrospectionServiceNode:https://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/services/introspection_service.cppnamespacedemo_nodes_cpp{classIntrospectionServiceNode:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitIntrospectionServiceNode(constrclcpp::NodeOptions&options):Node("introspection_service",options){autohandle_add_two_ints=[this](conststd::shared_ptrrequest_header,conststd::shared_ptrrequest,std::shared_ptrresponse)->void{(void)request_header;RCLCPP_INFO(this->get_logger(),"Incoming request\na: %"PRId64" b: %"PRId64,request->a,request->b);response->sum=request->a+request->b;};// Create a service that will use the callback function to handle requests.srv_=create_service("add_two_ints",handle_add_two_ints);autoon_set_parameter_callback=[](std::vectorparameters){rcl_interfaces::msg::SetParametersResultresult;result.successful=true;for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="service_configure_introspection"){continue;}if(param.get_type()!=rclcpp::ParameterType::PARAMETER_STRING){result.successful=false;result.reason="must be a string";break;}if(param.as_string()!="disabled"&¶m.as_string()!="metadata"&¶m.as_string()!="contents"){result.successful=false;result.reason="must be one of 'disabled', 'metadata', or 'contents'";break;}}returnresult;};autopost_set_parameter_callback=[this](conststd::vector¶meters){for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="service_configure_introspection"){continue;}rcl_service_introspection_state_tintrospection_state=RCL_SERVICE_INTROSPECTION_OFF;if(param.as_string()=="disabled"){introspection_state=RCL_SERVICE_INTROSPECTION_OFF;}elseif(param.as_string()=="metadata"){introspection_state=RCL_SERVICE_INTROSPECTION_METADATA;}elseif(param.as_string()=="contents"){introspection_state=RCL_SERVICE_INTROSPECTION_CONTENTS;}this->srv_->configure_introspection(this->get_clock(),rclcpp::SystemDefaultsQoS(),introspection_state);break;}};on_set_parameters_callback_handle_=this->add_on_set_parameters_callback(on_set_parameter_callback);post_set_parameters_callback_handle_=this->add_post_set_parameters_callback(post_set_parameter_callback);this->declare_parameter("service_configure_introspection","disabled");}private:rclcpp::Service::SharedPtrsrv_;rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtron_set_parameters_callback_handle_;rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtrpost_set_parameters_callback_handle_;};}// namespace demo_nodes_cppService introspection is disable in default, so users need to enable it to callconfigure_introspectionon service server. +In this demo,IntrospectionServiceNodeuses a parameter named`service_configure_introspectionto configure the service introspection state.1st we need to startIntrospectionServiceNode.$ros2rundemo_nodes_cppintrospection_serviceTo change service introspection state, we need to set theconfigure_introspectionparameter as following.### User data contents with metadata$ros2paramset/introspection_serviceservice_configure_introspectioncontents### Or only metadata$ros2paramset/introspection_serviceservice_configure_introspectionmetadata### To disable$ros2paramset/introspection_serviceservice_configure_introspectiondisabledIntrospectionClientNode:https://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/services/introspection_client.cppnamespacedemo_nodes_cpp{classIntrospectionClientNode:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitIntrospectionClientNode(constrclcpp::NodeOptions&options):Node("introspection_client",options){client_=create_client("add_two_ints");autoon_set_parameter_callback=[](std::vectorparameters){rcl_interfaces::msg::SetParametersResultresult;result.successful=true;for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="client_configure_introspection"){continue;}if(param.get_type()!=rclcpp::ParameterType::PARAMETER_STRING){result.successful=false;result.reason="must be a string";break;}if(param.as_string()!="disabled"&¶m.as_string()!="metadata"&¶m.as_string()!="contents"){result.successful=false;result.reason="must be one of 'disabled', 'metadata', or 'contents'";break;}}returnresult;};autopost_set_parameter_callback=[this](conststd::vector¶meters){for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="client_configure_introspection"){continue;}rcl_service_introspection_state_tintrospection_state=RCL_SERVICE_INTROSPECTION_OFF;if(param.as_string()=="disabled"){introspection_state=RCL_SERVICE_INTROSPECTION_OFF;}elseif(param.as_string()=="metadata"){introspection_state=RCL_SERVICE_INTROSPECTION_METADATA;}elseif(param.as_string()=="contents"){introspection_state=RCL_SERVICE_INTROSPECTION_CONTENTS;}this->client_->configure_introspection(this->get_clock(),rclcpp::SystemDefaultsQoS(),introspection_state);break;}};on_set_parameters_callback_handle_=this->add_on_set_parameters_callback(on_set_parameter_callback);post_set_parameters_callback_handle_=this->add_post_set_parameters_callback(post_set_parameter_callback);this->declare_parameter("client_configure_introspection","disabled");timer_=this->create_wall_timer(std::chrono::milliseconds(500),[this](){if(!client_->service_is_ready()){return;}if(!request_in_progress_){autorequest=std::make_shared();request->a=2;request->b=3;request_in_progress_=true;client_->async_send_request(request,[this](rclcpp::Client::SharedFuturecb_f){request_in_progress_=false;RCLCPP_INFO(get_logger(),"Result of add_two_ints: %ld",cb_f.get()->sum);});return;}});}private:rclcpp::Client::SharedPtrclient_;rclcpp::TimerBase::SharedPtrtimer_;rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtron_set_parameters_callback_handle_;rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtrpost_set_parameters_callback_handle_;boolrequest_in_progress_{false};};}// namespace demo_nodes_cppAnd then, we start and configureIntrospectionClientNodein the same way.$ros2rundemo_nodes_cppintrospection_clientChange service introspection state to setconfigure_introspectionparameter as following.### User data contents with metadata$ros2paramset/introspection_clientclient_configure_introspectioncontents### Or only metadata$ros2paramset/introspection_clientclient_configure_introspectionmetadata### To disable$ros2paramset/introspection_clientclient_configure_introspectiondisabledIn this tutorial the following is example output with service introspection stateCONTENTSonIntrospectionServiceNodeandMETADATAonIntrospectionClientNode. +To monitor service communication betweenIntrospectionClientNodeandIntrospectionServiceNode, let’s run it:$ros2serviceecho--flow-style/add_two_ints +info:event_type:REQUEST_SENTstamp:sec:1709432402nanosec:680094264client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,21,3]sequence_number:247request:[]response:[]--- +info:event_type:REQUEST_RECEIVEDstamp:sec:1709432402nanosec:680459568client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,20,4]sequence_number:247request:[{a:2,b:3}]response:[]--- +info:event_type:RESPONSE_SENTstamp:sec:1709432402nanosec:680765280client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,20,4]sequence_number:247request:[]response:[{sum:5}]--- +info:event_type:RESPONSE_RECEIVEDstamp:sec:1709432402nanosec:681027998client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,21,3]sequence_number:247request:[]response:[]--- +...You can see theevent_type:REQUEST_SENTandevent_type:RESPONSE_RECEIVED, those introspection service event take place inIntrospectionClientNode. +And those events does not include any contents inrequestandresponsefield, this is becauseIntrospectionClientNode’s service introspection state is set toMETADATA. +On the other hand,event_type:REQUEST_RECEIVEDandevent_type:RESPONSE_SENTevent fromIntrospectionServiceNodeincludesrequest:[{a:2,b:3}]andresponse:[{sum:5}]as introspection state is set toCONTENTS.Related contentservice introspection client example (rclcpp)andservice introspection service example (rclcpp).service introspection client and service example (rclpy).Service Introspection REP-2012. + +Code Examples: + +Language: unknown +namespacedemo_nodes_cpp{classIntrospectionServiceNode:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitIntrospectionServiceNode(constrclcpp::NodeOptions&options):Node("introspection_service",options){autohandle_add_two_ints=[this](conststd::shared_ptrrequest_header,conststd::shared_ptrrequest,std::shared_ptrresponse)->void{(void)request_header;RCLCPP_INFO(this->get_logger(),"Incoming request\na: %"PRId64" b: %"PRId64,request->a,request->b);response->sum=request->a+request->b;};// Create a service that will use the callback function to handle requests.srv_=create_service("add_two_ints",handle_add_two_ints);autoon_set_parameter_callback=[](std::vectorparameters){rcl_interfaces::msg::SetParametersResultresult;result.successful=true;for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="service_configure_introspection"){continue;}if(param.get_type()!=rclcpp::ParameterType::PARAMETER_STRING){result.successful=false;result.reason="must be a string";break;}if(param.as_string()!="disabled"&¶m.as_string()!="metadata"&¶m.as_string()!="contents"){result.successful=false;result.reason="must be one of 'disabled', 'metadata', or 'contents'";break;}}returnresult;};autopost_set_parameter_callback=[this](conststd::vector¶meters){for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="service_configure_introspection"){continue;}rcl_service_introspection_state_tintrospection_state=RCL_SERVICE_INTROSPECTION_OFF;if(param.as_string()=="disabled"){introspection_state=RCL_SERVICE_INTROSPECTION_OFF;}elseif(param.as_string()=="metadata"){introspection_state=RCL_SERVICE_INTROSPECTION_METADATA;}elseif(param.as_string()=="contents"){introspection_state=RCL_SERVICE_INTROSPECTION_CONTENTS;}this->srv_->configure_introspection(this->get_clock(),rclcpp::SystemDefaultsQoS(),introspection_state);break;}};on_set_parameters_callback_handle_=this->add_on_set_parameters_callback(on_set_parameter_callback);post_set_parameters_callback_handle_=this->add_post_set_parameters_callback(post_set_parameter_callback);this->declare_parameter("service_configure_introspection","disabled");}private:rclcpp::Service::SharedPtrsrv_;rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtron_set_parameters_callback_handle_;rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtrpost_set_parameters_callback_handle_;};}// namespace demo_nodes_cpp + +Language: unknown +$ros2rundemo_nodes_cppintrospection_service + +Language: unknown +### User data contents with metadata$ros2paramset/introspection_serviceservice_configure_introspectioncontents### Or only metadata$ros2paramset/introspection_serviceservice_configure_introspectionmetadata### To disable$ros2paramset/introspection_serviceservice_configure_introspectiondisabled + +Language: unknown +namespacedemo_nodes_cpp{classIntrospectionClientNode:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitIntrospectionClientNode(constrclcpp::NodeOptions&options):Node("introspection_client",options){client_=create_client("add_two_ints");autoon_set_parameter_callback=[](std::vectorparameters){rcl_interfaces::msg::SetParametersResultresult;result.successful=true;for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="client_configure_introspection"){continue;}if(param.get_type()!=rclcpp::ParameterType::PARAMETER_STRING){result.successful=false;result.reason="must be a string";break;}if(param.as_string()!="disabled"&¶m.as_string()!="metadata"&¶m.as_string()!="contents"){result.successful=false;result.reason="must be one of 'disabled', 'metadata', or 'contents'";break;}}returnresult;};autopost_set_parameter_callback=[this](conststd::vector¶meters){for(constrclcpp::Parameter¶m:parameters){if(param.get_name()!="client_configure_introspection"){continue;}rcl_service_introspection_state_tintrospection_state=RCL_SERVICE_INTROSPECTION_OFF;if(param.as_string()=="disabled"){introspection_state=RCL_SERVICE_INTROSPECTION_OFF;}elseif(param.as_string()=="metadata"){introspection_state=RCL_SERVICE_INTROSPECTION_METADATA;}elseif(param.as_string()=="contents"){introspection_state=RCL_SERVICE_INTROSPECTION_CONTENTS;}this->client_->configure_introspection(this->get_clock(),rclcpp::SystemDefaultsQoS(),introspection_state);break;}};on_set_parameters_callback_handle_=this->add_on_set_parameters_callback(on_set_parameter_callback);post_set_parameters_callback_handle_=this->add_post_set_parameters_callback(post_set_parameter_callback);this->declare_parameter("client_configure_introspection","disabled");timer_=this->create_wall_timer(std::chrono::milliseconds(500),[this](){if(!client_->service_is_ready()){return;}if(!request_in_progress_){autorequest=std::make_shared();request->a=2;request->b=3;request_in_progress_=true;client_->async_send_request(request,[this](rclcpp::Client::SharedFuturecb_f){request_in_progress_=false;RCLCPP_INFO(get_logger(),"Result of add_two_ints: %ld",cb_f.get()->sum);});return;}});}private:rclcpp::Client::SharedPtrclient_;rclcpp::TimerBase::SharedPtrtimer_;rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtron_set_parameters_callback_handle_;rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtrpost_set_parameters_callback_handle_;boolrequest_in_progress_{false};};}// namespace demo_nodes_cpp + +Language: unknown +$ros2rundemo_nodes_cppintrospection_client + +Language: unknown +### User data contents with metadata$ros2paramset/introspection_clientclient_configure_introspectioncontents### Or only metadata$ros2paramset/introspection_clientclient_configure_introspectionmetadata### To disable$ros2paramset/introspection_clientclient_configure_introspectiondisabled + +Language: unknown +$ros2serviceecho--flow-style/add_two_ints +info:event_type:REQUEST_SENTstamp:sec:1709432402nanosec:680094264client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,21,3]sequence_number:247request:[]response:[]--- +info:event_type:REQUEST_RECEIVEDstamp:sec:1709432402nanosec:680459568client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,20,4]sequence_number:247request:[{a:2,b:3}]response:[]--- +info:event_type:RESPONSE_SENTstamp:sec:1709432402nanosec:680765280client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,20,4]sequence_number:247request:[]response:[{sum:5}]--- +info:event_type:RESPONSE_RECEIVEDstamp:sec:1709432402nanosec:681027998client_gid:[1,15,0,18,86,208,115,86,0,0,0,0,0,0,21,3]sequence_number:247request:[]response:[]--- +... diff --git "a/exported_docs/ros2/Configuring_environment\357\203\201.txt" "b/exported_docs/ros2/Configuring_environment\357\203\201.txt" new file mode 100644 index 0000000..fb9e5da --- /dev/null +++ "b/exported_docs/ros2/Configuring_environment\357\203\201.txt" @@ -0,0 +1,77 @@ +Title: Configuring environment +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html +Section: Installation +-------------------------------------------------------------------------------- + +Configuring environmentGoal:This tutorial will show you how to prepare your ROS 2 environment.Tutorial level:BeginnerTime:5 minutesContentsBackgroundPrerequisitesTasks1 Source the setup files2 Add sourcing to your shell startup script3 Check environment variablesSummaryNext stepsBackgroundROS 2 relies on the notion of combining workspaces using the shell environment. +“Workspace” is a ROS term for the location on your system where you’re developing with ROS 2. +The core ROS 2 workspace is called the underlay. +Subsequent local workspaces are called overlays. +When developing with ROS 2, you will typically have several workspaces active concurrently.Combining workspaces makes developing against different versions of ROS 2, or against different sets of packages, easier. +It also allows the installation of several ROS 2 distributions (or “distros”, e.g. Dashing and Eloquent) on the same computer and switching between them.This is accomplished by sourcing setup files every time you open a new shell, or by adding the source command to your shell startup script once. +Without sourcing the setup files, you won’t be able to access ROS 2 commands, or find or use ROS 2 packages. +In other words, you won’t be able to use ROS 2.PrerequisitesBefore starting these tutorials, install ROS 2 by following the instructions on the ROS 2Installationpage.The commands used in this tutorial assume you followed the binary packages installation guide for your operating system (deb packages for Linux). +You can still follow along if you built from source, but the path to your setup files will likely be different. +You also won’t be able to use thesudoaptinstallros--command (used frequently in the beginner level tutorials) if you install from source.If you are using Linux or macOS, but are not already familiar with the shell,this tutorialwill help.Tasks1 Source the setup filesYou will need to run this command on every new shell you open to have access to the ROS 2 commands, like so:LinuxmacOSWindows# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zshsource/opt/ros/jazzy/setup.bash. ~/ros2_install/ros2-osx/setup.bashcall C:\dev\ros2\local_setup.batNoteThe exact command depends on where you installed ROS 2. +If you’re having problems, ensure the file path leads to your installation.2 Add sourcing to your shell startup scriptIf you don’t want to have to source the setup file every time you open a new shell (skipping task 1), then you can add the command to your shell startup script:LinuxmacOSWindowsecho "source /opt/ros/jazzy/setup.bash" >> ~/.bashrcTo undo this, locate your system’s shell startup script and remove the appended source command.echo "source ~/ros2_install/ros2-osx/setup.bash" >> ~/.bash_profileTo undo this, locate your system’s shell startup script and remove the appended source command.Only for PowerShell users, create a folder in ‘My Documents’ called ‘WindowsPowerShell’. +Within ‘WindowsPowerShell’, create file ‘Microsoft.PowerShell_profile.ps1’. +Inside the file, paste:C:\dev\ros2_jazzy\local_setup.ps1PowerShell will request permission to run this script everytime a new shell is opened. +To avoid that issue you can run:Unblock-File C:\dev\ros2_jazzy\local_setup.ps1To undo this, remove the new ‘Microsoft.PowerShell_profile.ps1’ file.3 Check environment variablesSourcing ROS 2 setup files will set several environment variables necessary for operating ROS 2. +If you ever have problems finding or using your ROS 2 packages, make sure that your environment is properly set up using the following command:LinuxmacOSWindowsprintenv | grep -i ROSprintenv | grep -i ROSset | findstr -i ROSCheck that variables likeROS_DISTROandROS_VERSIONare set.ROS_VERSION=2ROS_PYTHON_VERSION=3ROS_DISTRO=jazzyIf the environment variables are not set correctly, return to the ROS 2 package installation section of the installation guide you followed. +If you need more specific help (because environment setup files can come from different places), you canget answersfrom the community.3.1 TheROS_DOMAIN_IDvariableSee thedomain IDarticle for details on ROS domain IDs.Once you have determined a unique integer for your group of ROS 2 nodes, you can set the environment variable with the following command:LinuxmacOSWindowsexport ROS_DOMAIN_ID=To maintain this setting between shell sessions, you can add the command to your shell startup script:echo "export ROS_DOMAIN_ID=" >> ~/.bashrcexport ROS_DOMAIN_ID=To maintain this setting between shell sessions, you can add the command to your shell startup script:echo "export ROS_DOMAIN_ID=" >> ~/.bash_profileset ROS_DOMAIN_ID=If you want to make this permanent between shell sessions, also run:setx ROS_DOMAIN_ID 3.2 TheROS_AUTOMATIC_DISCOVERY_RANGEvariableBy default, ROS 2 communication is not limited to localhost.ROS_AUTOMATIC_DISCOVERY_RANGEenvironment variable allows you to limit ROS 2 discovery range. +UsingROS_AUTOMATIC_DISCOVERY_RANGEis helpful in certain settings, such as classrooms, where multiple robots may publish to the same topic causing strange behaviors. +SeeImproved Dynamic Discoveryfor more details.SummaryThe ROS 2 development environment needs to be correctly configured before use. +This can be done in two ways: either sourcing the setup files in every new shell you open, or adding the source command to your startup script.If you ever face any problems locating or using packages with ROS 2, the first thing you should do is check your environment variables and ensure they are set to the version and distro you intended.Next stepsNow that you have a working ROS 2 installation and you know how to source its setup files, you can start learning the ins and outs of ROS 2 with theturtlesim tool. + +Code Examples: + +Language: unknown +# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zshsource/opt/ros/jazzy/setup.bash + +Language: unknown +. ~/ros2_install/ros2-osx/setup.bash + +Language: unknown +call C:\dev\ros2\local_setup.bat + +Language: unknown +echo "source /opt/ros/jazzy/setup.bash" >> ~/.bashrc + +Language: unknown +echo "source ~/ros2_install/ros2-osx/setup.bash" >> ~/.bash_profile + +Language: unknown +C:\dev\ros2_jazzy\local_setup.ps1 + +Language: unknown +Unblock-File C:\dev\ros2_jazzy\local_setup.ps1 + +Language: unknown +printenv | grep -i ROS + +Language: unknown +printenv | grep -i ROS + +Language: unknown +set | findstr -i ROS + +Language: unknown +ROS_VERSION=2ROS_PYTHON_VERSION=3ROS_DISTRO=jazzy + +Language: unknown +export ROS_DOMAIN_ID= + +Language: unknown +echo "export ROS_DOMAIN_ID=" >> ~/.bashrc + +Language: unknown +export ROS_DOMAIN_ID= + +Language: unknown +echo "export ROS_DOMAIN_ID=" >> ~/.bash_profile + +Language: unknown +set ROS_DOMAIN_ID= + +Language: unknown +setx ROS_DOMAIN_ID diff --git "a/exported_docs/ros2/Contributing_to_ROS_2_Documentation\357\203\201.txt" "b/exported_docs/ros2/Contributing_to_ROS_2_Documentation\357\203\201.txt" new file mode 100644 index 0000000..c1971b5 --- /dev/null +++ "b/exported_docs/ros2/Contributing_to_ROS_2_Documentation\357\203\201.txt" @@ -0,0 +1,148 @@ +Title: Contributing to ROS 2 Documentation +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Contributing/Contributing-To-ROS-2-Documentation.html +Section: Installation +-------------------------------------------------------------------------------- + +Contributing to ROS 2 DocumentationTable of ContentsBranch structureSource structureBuilding the site locallyBuilding the site for one branchView Site Through Github CIBuilding the site for all branchesChecking for broken linksMigrating Pages from the ROS WikiMigrating a Wiki FileBuilding the Site with GitHub CodespacesBuilding the Site with DevcontainerWriting pagesTable of ContentsHeadingsListsCode FormattingImagesReferences and LinksContributions to this site are most welcome. +This page explains how to contribute to ROS 2 Documentation. +Please be sure to read the below sections carefully before contributing.The site is built usingSphinx, and more particularly usingSphinx multiversion.Branch structureThe source code of documentation is located in theROS 2 Documentation GitHub repository. +This repository is set up with one branch per ROS 2 distribution to handle differences between the distributions. +If a change is common to all ROS 2 distributions, it should be made to therollingbranch (and then will be backported as appropriate). +If a change is specific to a particular ROS 2 distribution, it should be made to the respective branch.Source structureThe source files for the site are all located under thesourcesubdirectory. +Templates for various sphinx plugins are located undersource/_templates. +The root directory contains configuration and files required to locally build the site for testing.Building the site locallyStart by creatingvenvto build the documentation:#activatethevenvpython3 -m venv ros2doc#activatevenvsource ros2doc/bin/activateAnd install requirements located in therequirements.txtfile:LinuxmacOSWindowspip install -r requirements.txt -c constraints.txtpip install -r requirements.txt -c constraints.txtpython -m pip install -r requirements.txt -c constraints.txtIn order for Sphinx to be able to generate diagrams, thedotcommand must be available.LinuxmacOSWindowssudo apt update ; sudo apt install graphvizbrew install graphvizDownload an installer fromthe Graphviz Download pageand install it. +Make sure to allow the installer to add it to the Windows%PATH%, otherwise Sphinx will not be able to find it.Building the site for one branchTo build the site for just this branch, typemakehtmlat the top-level of the repository. +This is the recommended way to test out local changes.make htmlThe build process can take some time. +To see the output, openbuild/html/index.htmlin your browser.You can also run the documentation tests locally (usingdoc8) with the following command:make testView Site Through Github CIFor small changes to the ROS 2 Docs you can view your changes as rendered HTML using artifacts generated in our Github Actions. +The “build” action produces the entire ROS Docs as a downloadable Zip file that contains all HTML fordocs.ros.orgThis build action is triggered after passing the test action and lint action.To download and view your changes first go to your pull request and under the title click the “Checks” tab. +On the left hand side of the checks page, click on the “Test” section under the “tests” section click on “build” dialog. +This will open a menu on the right, where you can click on “Upload document artifacts” and scroll to the bottom to see the download link for the Zipped’ HTML files under the heading “Artifact download URL”.Building the site for all branchesTo build the site for all branches, typemakemultiversionfrom therollingbranch. +This has two drawbacks:The multiversion plugin doesn’t understand how to do incremental builds, so it always rebuilds everything. +This can be slow.When typingmakemultiversion, it will always check out exactly the branches listed in theconf.pyfile. +That means that local changes will not be shown.To show local changes in the multiversion output, you must first commit the changes to a local branch. +Then you must edit theconf.pyfile and change thesmv_branch_whitelistvariable to point to your branch.Checking for broken linksTo check for broken links on the site, run:make linkcheckThis will check the entire site for broken links, and output the results to the screen andbuild/linkcheck.Migrating Pages from the ROS WikiThe first step in migrating a page from theROS Wikito the ROS 2 documentation is to determine if the page needs to be migrated. +Check if the content, or something similar, is available onhttps://docs.ros.org/en/rollingby searching for related terms. +If it has already been migrated, congratulations! +You are done. +If it hasn’t been migrated, then consider whether it is worth keeping. +Pages that you or others find useful, and refer to regularly, are good candidates assuming they have not been superseded by other documentation. +Pages for ROS projects and features that are no longer supported by a current distribution should not be migrated.The next step for migrating a ROS Wiki page is to determine the correct location for the migrated page. +Only ROS Wiki pages that cover core ROS concepts belong in the ROS Documentation, these pages should be migrated to a logical location within the ROS documentation. +Package specific documentation should be migrated to the package-level documentation generated in the package’s source repository. +Once the package level documentation has been updated it will be visibleas part of the package-level documentation. +If you are unsure whether and where to migrate a page, please get in touch via an issue onhttps://github.com/ros2/ros2_documentationor onhttps://discourse.ros.org.Once you’ve determined that a ROS Wiki page is worth migrating, and found an appropriate landing spot in the ROS documentation, the next step in the migration process is to set up the conversion tools necessary to migrate the page. +In most cases the only tools necessary to migrate a single ROS Wiki page to the ROS Docs are thePanDoccommand line tool and a text editor. +PanDoc is supported by most modern operating systems using the installation instruction found on their website. +It is worth noting that the ROS Wiki uses an older wiki technology (MoinMoin), so the markup language used is an obscure dialect of theMediaWikiformat. +We’ve found that the easiest way to migrate a page from the ROS Wiki is to convert it from HTML into reStructured text using PanDoc.Migrating a Wiki FileClone the appropriate repository. If you are migrating a page to the official documentation hosted here, then you should clonehttps://github.com/ros2/ros2_documentation.Create a new Github branch for your migrated page. We suggest something likepagename-migration.Download the appropriate ROS Wiki page to an html file using wget or a similar tool (e.g.wget-Ourdf.htmlhttps://wiki.ros.org/urdf). +Alternatively you can use your web browser to save the page’s HTML.Next you need to remove the extraneous HTML in the file you downloaded +Using your browser’s developer mode, find the name of the first useful HTML element in the Wiki page. +In most cases all of the HTML between the third line of the file, starting with thetag, through the start of the first

tag can be safely removed. +In the case where there is a table of contents, the first useful tag may be an

tag. Similarly, the ROS wiki contains some footer text that starts withand ends just abovethat can also be removed.Convert your html file by running a PanDoc conversion between HTML and restructured text. +The following command coverts an HTML file to the equivalent reStructured text files:pandoc-fhtml-trsturdf.html>URDF.rst.Attempt to build your new documentation using themakehtmlcommand. +There may be errors and warnings that you will need to address.CAREFULLYread through the entire page making sure the material is up to date for ROS 2. +Check every single link to make sure it points to the appropriate location on docs.ros.org. +Internal document references must be updated to point to the equivalent ROS 2 material. +Your updated document should not point to the ROS Wiki unless it is absolutely necessary. +This process may require you alter the document considerably, and you may need to pull multiple wiki files. +You should verify that every code sample in the document is working correctly under ROS 2.Find and download any images that may be in the old document. The easiest way to do this is to right click in the browser and download all of the images. Alternatively you can find images by searching fortags in the HTML file.For each image files downloaded update the image file links to point to the correct image directory for the ROS Docs. +If any of the images require updating, or could be replaced with aMermaidchart, please make this change. +Be aware that Mermaid.js is only supported in the core ROS 2 documenation currently.Once your document is complete add a table of contents to the top of your new rst document using the appropriate Sphinx commands. +This block should replace any existing table of contents from the old ROS Wiki.Issue your pull request. +Make sure to point to the original ROS Wiki file for reference.Once your pull request has been accepted please add a note to the top of the page on the original ROS Wiki article pointing to the new documentation page.For a real-world example of this process in action, please refer to the ROS 2 Image Processing Pipeline in boththe ROS 2 Docsand in the originalROS Wiki. +The completed documentation page can be found in theROS 2 package documentation for image_pipeline.Building the Site with GitHub CodespacesFirst, you need to have a GitHub account (if you don’t have one, you can create one for free). +Then, you need to go to theROS 2 Documentation GitHub repository. +After that, you can open the repository in Codespaces, it can be done just by clicking on the “Code” button on the repository page, then choose “Open with Codespaces” from the dropdown menu.After that, you will be redirected to your Codespaces page, where you can see the progress of the Codespaces creation. +Once it is done, a Visual Studio Code tab will be opened in your browser. You can open the terminal by clicking on the “Terminal” tab in the top panel or by pressingCtrl-J.In this terminal, you can run any command you want, for example, you can run the following command to build the site for just this branch:make htmlFinally, to view the site, you can click on the “Go Live” button in the right bottom panel and then, it will open the site in a new tab in your browser (you will need to browse to thebuild/htmlfolder).Building the Site with DevcontainerROS 2 Documentation GitHub repositoryalso supportsDevcontainerdevelopment environment with Visual Studio Code. +This will enable you to build the documentation much easier without changing your operating system.SeeSetup ROS 2 with VSCode and Docker [community-contributed]to install VS Code and Docker before the following procedure.Clone repository and start VS Code:git clone https://github.com/ros2/ros2_documentationcd ./ros2_documentationcode .To useDevcontainer, you need to install “Remote Development” Extension within VS Code search in Extensions (CTRL+SHIFT+X) for it.And then, useView->CommandPalette...orCtrl+Shift+Pto open the command palette. +Search for the commandDevContainers:ReopeninContainerand execute it. +This will build your development docker container for you automatically.To build the documentation, open a terminal usingView->TerminalorCtrl+Shift+`andNewTerminalin VS Code. +Inside the terminal, you can build the documentation:make htmlWriting pagesThe ROS 2 documentation website uses thereStructuredTextformat, which is the default plaintext markup language used by Sphinx. +This section is a brief introduction toreStructuredTextconcepts, syntax, and best practices.You can refer toreStructuredText User Documentationfor a detailed technical specification.Table of ContentsThere are two types of directives used for the generation of a table of contents,..toctree::and..contents::. +The..toctree::is used in top-level pages likeTutorials.rstto set ordering and visibility of its child pages. +This directive creates both left navigation panel and in-page navigation links to the child pages listed. +It helps readers to understand the structure of separate documentation sections and navigate between pages...toctree:::maxdepth:1The..contents::directive is used for the generation of a table of contents for that particular page. +It parses all present headings in a page and builds an in-page nested table of contents. +It helps readers to see an overview of the content and navigate inside a page.The..contents::directive supports the definition of maximum depth of nested sections. +Using:depth:2will only show Sections and Subsections in the table of contents...contents::Table of Contents:depth:2:local:HeadingsThere are four main Heading types used in the documentation. +Note that the number of symbols has to match the length of the title.Page Title Header=================Section Header--------------2 Subsection Header^^^^^^^^^^^^^^^^^^^2.4 Subsubsection Header~~~~~~~~~~~~~~~~~~~~~~~~We usually use one digit for numbering subsections and two digits (dot separated) for numbering subsubsections in Tutorials and How-To-Guides.ListsStars*are used for listing unordered items with bullet points and number sign#.is used for listing numbered items. +Both of them support nested definitions and will render accordingly.*bullet point*bullet point nested*bullet point nested*bullet point#.first listed item#.second lited itemCode FormattingIn-text code can be formatted usingbackticksfor showinghighlightedcode.In-text code can be formatted using``backticks``for showing``highlighted``code.Code blocks inside a page need to be captured using..code-block::directive...code-block::supports code highlighting for syntaxes likeC++,YAML,console,bash, and more. +Code inside the directive needs to be indented...code-block::C++intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}ImagesImages can be inserted using the..image::directive...image::images/turtlesim_follow1.pngReferences and LinksExternal linksThe syntax of creating links to external web pages is shown below.`ROS Docs`_The above link will appear asROS Docs. +Note the underscore after the final single quote.Internal linksThe:doc:directive is used to create in-text links to other pages.:doc:`Quality of Service <../Tutorials/Quality-of-Service>`Note that the relative path to the file is used.Therefdirective is used to make links to specific parts of a page. +These could be headings, images or code sections inside the current or different page.Definition of explicit target right before the desired object is required. +In the example below, the target is defined as_talker-listenerone line before the headingTrysomeexamples..._talker-listener:Try some examples-----------------Now the link from any page in the documentation to that header can be created.:ref:`talker-listener demo `This link will navigate a reader to the target page with an HTML anchor link#talker-listener.MacrosMacros can be used to simplify writing documentation that targets multiple distributions.Use a macro by including the macro name in curly braces. +For example, when generating the docs for Rolling on therollingbranch:UseBecomes (for Rolling)Example{DISTRO}rollingros-{DISTRO}-pkg{DISTRO_TITLE}RollingROS 2 {DISTRO_TITLE}{DISTRO_TITLE_FULL}Rolling RidleyROS 2 {DISTRO_TITLE_FULL}{REPOS_FILE_BRANCH}rollinggit checkout {REPOS_FILE_BRANCH}The same file can be used on multiple branches (i.e., for multiple distros) and the generated content will be distro-specific. + +Code Examples: + +Language: unknown +#activatethevenvpython3 -m venv ros2doc#activatevenvsource ros2doc/bin/activate + +Language: unknown +pip install -r requirements.txt -c constraints.txt + +Language: unknown +pip install -r requirements.txt -c constraints.txt + +Language: unknown +python -m pip install -r requirements.txt -c constraints.txt + +Language: unknown +sudo apt update ; sudo apt install graphviz + +Language: unknown +brew install graphviz + +Language: unknown +make html + +Language: unknown +make test + +Language: unknown +make linkcheck + +Language: unknown +make html + +Language: unknown +git clone https://github.com/ros2/ros2_documentationcd ./ros2_documentationcode . + +Language: unknown +make html + +Language: unknown +..toctree:::maxdepth:1 + +Language: unknown +..contents::Table of Contents:depth:2:local: + +Language: unknown +Page Title Header=================Section Header--------------2 Subsection Header^^^^^^^^^^^^^^^^^^^2.4 Subsubsection Header~~~~~~~~~~~~~~~~~~~~~~~~ + +Language: unknown +*bullet point*bullet point nested*bullet point nested*bullet point + +Language: unknown +#.first listed item#.second lited item + +Language: unknown +In-text code can be formatted using``backticks``for showing``highlighted``code. + +Language: unknown +..code-block::C++intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +..image::images/turtlesim_follow1.png + +Language: unknown +`ROS Docs`_ + +Language: unknown +:doc:`Quality of Service <../Tutorials/Quality-of-Service>` + +Language: unknown +.._talker-listener:Try some examples----------------- + +Language: unknown +:ref:`talker-listener demo ` diff --git "a/exported_docs/ros2/Contributing\357\203\201.txt" "b/exported_docs/ros2/Contributing\357\203\201.txt" new file mode 100644 index 0000000..5eb837f --- /dev/null +++ "b/exported_docs/ros2/Contributing\357\203\201.txt" @@ -0,0 +1,23 @@ +Title: Contributing +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Contributing.html +Section: Installation +-------------------------------------------------------------------------------- + +ContributingTable of ContentsTenetsDiscussions and supportContributing codeA few things to remember before you start contributing to the ROS 2 project.TenetsRespect what came beforeROS has been around for more than a decade and is used by developers and across the world. +Keep a humble attitude and an open mindset while contributing.Engage Open Robotics as early as possibleOpen Robotics acts as a gate-keeper and advocate for the ROS community. +Rely on their expertise and technical judgement from the design phase.Start discussions with Open Robotics and the community early. +Long time ROS contributors may have a clearer vision of the bigger picture. +If you implement a feature and send a pull request without discussing with the community first, you are taking the risk of it being rejected, or you may be asked to largely rethink your design.Opening issues or using Discourse to socialize an idea before starting the implementation is generally preferable.Adopt community best-practices whenever possible instead of ad-hoc processesThink about your end-user’s experience when developing and contributing. +Avoid using non-standard tools or libraries that may not be accessible to everyone.Think about the community as a wholeThink about the bigger picture. +There are developers building different robots with different constraints. +ROS needs to accommodate requirements of the whole community.There are a number of ways you can contribute to the ROS 2 project.Discussions and supportSome of the easiest ways to contribute to ROS 2 involve engaging in community discussions and support. +You can find more information on how to pitch in on theContactpage.Contributing codeSetting up your development environmentTo get started, you’ll want to install from source; followthe source installation instructionsfor your platform.Development GuidesROS 2 developer guideCode style and language versionsQuality guide: ensuring code qualityROS Build FarmsWindows Tips and TricksContributing to ROS 2 DocumentationWhat to work onWe have identified a number of tasks that could be worked on by community members: they can be listed bysearching across the ROS 2 repositories for issues labeled as “help wanted”. +If you see something on that list that you would like to work on, please comment on the item to let others know that you are looking into it.We also have a label for issues that we think should be more accessible for first-time contributors,labeled “good first issue”. +If you are interested in contributing to the ROS 2 project, we encourage you to take a look at those issues first. +If you’d like to cast a wider net, we welcome contributions on any open issue (or others that you might propose), particularly tasks that have a milestone signifying they’re targeted for the next ROS 2 release (the milestone will be the next release’s e.g. ‘crystal’).If you have some code to contribute that fixes a bug or improves documentation, please submit it as a pull request to the relevant repository. +For larger changes, it is a good idea to discuss the proposalon the ROS 2 forumbefore you start to work on it so that you can identify if someone else is already working on something similar. +If your proposal involves changes to the APIs, it is especially recommended that you discuss the approach before starting work.Submitting your code changesCode contributions should be made via pull requests tothe appropriate ros2 repositories.We ask all contributors to follow the practices explained inthe developer guide.Please be sure torun testsfor your code changes because most packages have tests that check that the code complies with our style guidelines.Becoming a core maintainerThe ROS 2 maintainers ensure that the project is generally making progress. +The responsibilities of the maintainers include:Reviewing incoming code contributions for style, quality, and overall fit into the goals of the repository/ROS 2.Ensuring that CI continues to stay green.Merging pull requests that meet the quality and CI standards above.Addressing issues opened up by users.Each repository in theros2andamentorganizations has a separate set of maintainers. +Becoming a maintainer of one or more of those repositories is an invitation-only process, and generally involves the following steps:Within the last year, have a substantial number of code contributions to the repository.Within the last year, do a substantial number of reviews on incoming pull requests to the repository.Approximately every 3 months, the ROS 2 team will review the contributions in all of the repositories and send out invitations to new maintainers. +Once the invitation is accepted, the new maintainer will be asked to go through a short training process on the mechanisms and policies of the ROS 2 repositories. +After that training process is completed, the new maintainer will be given write access to the appropriate repositories. \ No newline at end of file diff --git "a/exported_docs/ros2/Creating_a_content_filtering_subscription\357\203\201.txt" "b/exported_docs/ros2/Creating_a_content_filtering_subscription\357\203\201.txt" new file mode 100644 index 0000000..c2ee40f --- /dev/null +++ "b/exported_docs/ros2/Creating_a_content_filtering_subscription\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: Creating a content filtering subscription +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos/Content-Filtering-Subscription.html +Section: Installation +-------------------------------------------------------------------------------- + +Creating a content filtering subscriptionGoal:Create a content filtering subscription.Tutorial level:AdvancedTime:15 minutesTable of ContentsOverviewRMW SupportInstalling the demoTemperature filtering demoRelated contentOverviewROS 2 applications typically consist of topics to transmit data from publishers to subscriptions. +Basically, subscriptions receive all published data from publishers on the topic. +But sometimes, a subscription might be interested in only a subset of the data which is being sent by publishers. +A content filtering subscription allows to receive only the data of interest for the application.In this demo, we’ll be highlighting how to create a content filtering subscription and how they work.RMW SupportContent filtering subscriptions require RMW implementation support.Content-Filtering-Subscription Support Statusrmw_fastrtpssupportedrmw_connextddssupportedrmw_cycloneddsnot supportedCurrently all RMW implementations that support content filtering subscriptions areDDSbased. +That means that the supported filtering expressions and parameters are also dependent onDDS, you can refer toDDS specificationAnnexB-SyntaxforQueriesandFiltersfor details.Installing the demoSee theinstallation instructionsfor details on installing ROS 2.If you’ve installed ROS 2 from packages, ensure that you haveros-jazzy-demo-nodes-cppinstalled. +If you downloaded the archive or built ROS 2 from source, it will already be part of the installation.Temperature filtering demoThis demo shows how a content filtering subscription can be used to only receive temperature values that are out of the acceptable temperature range, detecting emergencies. +The content filtering subscription filters out the uninteresting temperature data, so that the subscription callback is not issued.ContentFilteringPublisher:https://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/topics/content_filtering_publisher.cpp#include#include#include#include#include"rclcpp/rclcpp.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"std_msgs/msg/float32.hpp"#include"demo_nodes_cpp/visibility_control.h"usingnamespacestd::chrono_literals;namespacedemo_nodes_cpp{// The simulated temperature data starts from -100.0 and ends at 150.0 with a step size of 10.0constexprstd::arrayTEMPERATURE_SETTING{-100.0f,150.0f,10.0f};// Create a ContentFilteringPublisher class that subclasses the generic rclcpp::Node base class.// The main function below will instantiate the class as a ROS node.classContentFilteringPublisher:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitContentFilteringPublisher(constrclcpp::NodeOptions&options):Node("content_filtering_publisher",options){// Create a function for when messages are to be sent.setvbuf(stdout,NULL,_IONBF,BUFSIZ);autopublish_message=[this]()->void{msg_=std::make_unique();msg_->data=temperature_;temperature_+=TEMPERATURE_SETTING[2];if(temperature_>TEMPERATURE_SETTING[1]){temperature_=TEMPERATURE_SETTING[0];}RCLCPP_INFO(this->get_logger(),"Publishing: '%f'",msg_->data);// Put the message into a queue to be processed by the middleware.// This call is non-blocking.pub_->publish(std::move(msg_));};// Create a publisher with a custom Quality of Service profile.// Uniform initialization is suggested so it can be trivially changed to// rclcpp::KeepAll{} if the user wishes.// (rclcpp::KeepLast(7) -> rclcpp::KeepAll() fails to compile)rclcpp::QoSqos(rclcpp::KeepLast{7});pub_=this->create_publisher("temperature",qos);// Use a timer to schedule periodic message publishing.timer_=this->create_wall_timer(1s,publish_message);}private:floattemperature_=TEMPERATURE_SETTING[0];std::unique_ptrmsg_;rclcpp::Publisher::SharedPtrpub_;rclcpp::TimerBase::SharedPtrtimer_;};}// namespace demo_nodes_cppThe content filter is defined in the subscription side, publishers don’t need to be configured in any special way to allow content filtering. +TheContentFilteringPublishernode publishes simulated temperature data starting from -100.0 and ending at 150.0 with a step size of 10.0 every second.We can run the demo by running theros2rundemo_nodes_cppcontent_filtering_publisherexecutable (don’t forget to source the setup file first):$ros2rundemo_nodes_cppcontent_filtering_publisher[INFO][1651094594.822753479][content_filtering_publisher]:Publishing:'-100.000000'[INFO][1651094595.822723857][content_filtering_publisher]:Publishing:'-90.000000'[INFO][1651094596.822752996][content_filtering_publisher]:Publishing:'-80.000000'[INFO][1651094597.822752475][content_filtering_publisher]:Publishing:'-70.000000'[INFO][1651094598.822721485][content_filtering_publisher]:Publishing:'-60.000000'[INFO][1651094599.822696188][content_filtering_publisher]:Publishing:'-50.000000'[INFO][1651094600.822699217][content_filtering_publisher]:Publishing:'-40.000000'[INFO][1651094601.822744113][content_filtering_publisher]:Publishing:'-30.000000'[INFO][1651094602.822694805][content_filtering_publisher]:Publishing:'-20.000000'[INFO][1651094603.822735805][content_filtering_publisher]:Publishing:'-10.000000'[INFO][1651094604.822722094][content_filtering_publisher]:Publishing:'0.000000'[INFO][1651094605.822699960][content_filtering_publisher]:Publishing:'10.000000'[INFO][1651094606.822748946][content_filtering_publisher]:Publishing:'20.000000'[INFO][1651094607.822694017][content_filtering_publisher]:Publishing:'30.000000'[INFO][1651094608.822708798][content_filtering_publisher]:Publishing:'40.000000'[INFO][1651094609.822692417][content_filtering_publisher]:Publishing:'50.000000'[INFO][1651094610.822696426][content_filtering_publisher]:Publishing:'60.000000'[INFO][1651094611.822751913][content_filtering_publisher]:Publishing:'70.000000'[INFO][1651094612.822692231][content_filtering_publisher]:Publishing:'80.000000'[INFO][1651094613.822745549][content_filtering_publisher]:Publishing:'90.000000'[INFO][1651094614.822701982][content_filtering_publisher]:Publishing:'100.000000'[INFO][1651094615.822691465][content_filtering_publisher]:Publishing:'110.000000'[INFO][1651094616.822649070][content_filtering_publisher]:Publishing:'120.000000'[INFO][1651094617.822693616][content_filtering_publisher]:Publishing:'130.000000'[INFO][1651094618.822691832][content_filtering_publisher]:Publishing:'140.000000'[INFO][1651094619.822688452][content_filtering_publisher]:Publishing:'150.000000'[INFO][1651094620.822645327][content_filtering_publisher]:Publishing:'-100.000000'[INFO][1651094621.822689219][content_filtering_publisher]:Publishing:'-90.000000'[INFO][1651094622.822694292][content_filtering_publisher]:Publishing:'-80.000000'[...]ContentFilteringSubscriber:https://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/topics/content_filtering_subscriber.cpp#include"rclcpp/rclcpp.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"rcpputils/join.hpp"#include"std_msgs/msg/float32.hpp"#include"demo_nodes_cpp/visibility_control.h"namespacedemo_nodes_cpp{// Emergency temperature data less than -30 or greater than 100constexprstd::arrayEMERGENCY_TEMPERATURE{-30.0f,100.0f};// Create a ContentFilteringSubscriber class that subclasses the generic rclcpp::Node base class.// The main function below will instantiate the class as a ROS node.classContentFilteringSubscriber:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitContentFilteringSubscriber(constrclcpp::NodeOptions&options):Node("content_filtering_subscriber",options){setvbuf(stdout,NULL,_IONBF,BUFSIZ);// Create a callback function for when messages are received.autocallback=[this](conststd_msgs::msg::Float32&msg)->void{if(msg.dataEMERGENCY_TEMPERATURE[1]){RCLCPP_INFO(this->get_logger(),"I receive an emergency temperature data: [%f]",msg.data);}else{RCLCPP_INFO(this->get_logger(),"I receive a temperature data: [%f]",msg.data);}};// Initialize a subscription with a content filter to receive emergency temperature data that// are less than -30 or greater than 100.rclcpp::SubscriptionOptionssub_options;sub_options.content_filter_options.filter_expression="data < %0 OR data > %1";sub_options.content_filter_options.expression_parameters={std::to_string(EMERGENCY_TEMPERATURE[0]),std::to_string(EMERGENCY_TEMPERATURE[1])};sub_=create_subscription("temperature",10,callback,sub_options);if(!sub_->is_cft_enabled()){RCLCPP_WARN(this->get_logger(),"Content filter is not enabled since it's not supported");}else{RCLCPP_INFO(this->get_logger(),"subscribed to topic\"%s\"with content filter options\"%s, {%s}\"",sub_->get_topic_name(),sub_options.content_filter_options.filter_expression.c_str(),rcpputils::join(sub_options.content_filter_options.expression_parameters,", ").c_str());}}private:rclcpp::Subscription::SharedPtrsub_;};}// namespace demo_nodes_cppTo enable content filtering, applications can set the filtering expression and the expression parameters inSubscriptionOptions. +The application can also check if content filtering is enabled on the subscription.In this demo, theContentFilteringSubscribernode creates a content filtering subscription that receives a message only if the temperature value is less than -30.0 or greater than 100.0.As commented before, content filtering subscription support depends on the RMW implementation. +Applications can use theis_cft_enabledmethod to check if content filtering is actually enabled on the subscription.To test content filtering subscription, let’s run it:$ros2rundemo_nodes_cppcontent_filtering_subscriber[INFO][1651094590.682660703][content_filtering_subscriber]:subscribedtotopic"/temperature"withcontentfilteroptions"data < %0 OR data > %1, {-30.000000, 100.000000}"[INFO][1651094594.823805294][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-100.000000][INFO][1651094595.823419993][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-90.000000][INFO][1651094596.823410859][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-80.000000][INFO][1651094597.823350377][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-70.000000][INFO][1651094598.823282657][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-60.000000][INFO][1651094599.823297857][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-50.000000][INFO][1651094600.823355597][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-40.000000][INFO][1651094615.823315377][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[110.000000][INFO][1651094616.823258458][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[120.000000][INFO][1651094617.823323525][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[130.000000][INFO][1651094618.823315527][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[140.000000][INFO][1651094619.823331424][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[150.000000][INFO][1651094620.823271748][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-100.000000][INFO][1651094621.823343550][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-90.000000][INFO][1651094622.823286326][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-80.000000][INFO][1651094623.823371031][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-70.000000][INFO][1651094624.823333112][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-60.000000][INFO][1651094625.823266469][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-50.000000][INFO][1651094626.823284093][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-40.000000]You should see a message showing the content filtering options used and logs for each message received only if the temperature value is less than -30.0 or greater than 100.0.If content filtering is not supported by the RMW implementation, the subscription will still be created without content filtering enabled. +We can try that by executingRMW_IMPLEMENTATION=rmw_cyclonedds_cppros2rundemo_nodes_cppcontent_filtering_publisher.$RMW_IMPLEMENTATION=rmw_cyclonedds_cppros2rundemo_nodes_cppcontent_filtering_subscriber[WARN][1651096637.893842072][content_filtering_subscriber]:Contentfilterisnotenabledsinceitisnotsupported[INFO][1651096641.246043703][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-100.000000][INFO][1651096642.245833527][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-90.000000][INFO][1651096643.245743471][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-80.000000][INFO][1651096644.245833932][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-70.000000][INFO][1651096645.245916679][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-60.000000][INFO][1651096646.245861895][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-50.000000][INFO][1651096647.245946352][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-40.000000][INFO][1651096648.245934569][content_filtering_subscriber]:Ireceiveatemperaturedata:[-30.000000][INFO][1651096649.245877906][content_filtering_subscriber]:Ireceiveatemperaturedata:[-20.000000][INFO][1651096650.245939068][content_filtering_subscriber]:Ireceiveatemperaturedata:[-10.000000][INFO][1651096651.245911450][content_filtering_subscriber]:Ireceiveatemperaturedata:[0.000000][INFO][1651096652.245879830][content_filtering_subscriber]:Ireceiveatemperaturedata:[10.000000][INFO][1651096653.245858329][content_filtering_subscriber]:Ireceiveatemperaturedata:[20.000000][INFO][1651096654.245916370][content_filtering_subscriber]:Ireceiveatemperaturedata:[30.000000][INFO][1651096655.245933741][content_filtering_subscriber]:Ireceiveatemperaturedata:[40.000000][INFO][1651096656.245833975][content_filtering_subscriber]:Ireceiveatemperaturedata:[50.000000][INFO][1651096657.245971483][content_filtering_subscriber]:Ireceiveatemperaturedata:[60.000000]You can see the messageContentfilterisnotenabledbecause underlying RMW implementation does not support the feature, but the demo still successfully creates the normal subscription to receive all temperature data.Related contentcontent filtering examplesthat covers all interfaces for content filtering subscription.content filtering design PR + +Code Examples: + +Language: unknown +#include#include#include#include#include"rclcpp/rclcpp.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"std_msgs/msg/float32.hpp"#include"demo_nodes_cpp/visibility_control.h"usingnamespacestd::chrono_literals;namespacedemo_nodes_cpp{// The simulated temperature data starts from -100.0 and ends at 150.0 with a step size of 10.0constexprstd::arrayTEMPERATURE_SETTING{-100.0f,150.0f,10.0f};// Create a ContentFilteringPublisher class that subclasses the generic rclcpp::Node base class.// The main function below will instantiate the class as a ROS node.classContentFilteringPublisher:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitContentFilteringPublisher(constrclcpp::NodeOptions&options):Node("content_filtering_publisher",options){// Create a function for when messages are to be sent.setvbuf(stdout,NULL,_IONBF,BUFSIZ);autopublish_message=[this]()->void{msg_=std::make_unique();msg_->data=temperature_;temperature_+=TEMPERATURE_SETTING[2];if(temperature_>TEMPERATURE_SETTING[1]){temperature_=TEMPERATURE_SETTING[0];}RCLCPP_INFO(this->get_logger(),"Publishing: '%f'",msg_->data);// Put the message into a queue to be processed by the middleware.// This call is non-blocking.pub_->publish(std::move(msg_));};// Create a publisher with a custom Quality of Service profile.// Uniform initialization is suggested so it can be trivially changed to// rclcpp::KeepAll{} if the user wishes.// (rclcpp::KeepLast(7) -> rclcpp::KeepAll() fails to compile)rclcpp::QoSqos(rclcpp::KeepLast{7});pub_=this->create_publisher("temperature",qos);// Use a timer to schedule periodic message publishing.timer_=this->create_wall_timer(1s,publish_message);}private:floattemperature_=TEMPERATURE_SETTING[0];std::unique_ptrmsg_;rclcpp::Publisher::SharedPtrpub_;rclcpp::TimerBase::SharedPtrtimer_;};}// namespace demo_nodes_cpp + +Language: unknown +$ros2rundemo_nodes_cppcontent_filtering_publisher[INFO][1651094594.822753479][content_filtering_publisher]:Publishing:'-100.000000'[INFO][1651094595.822723857][content_filtering_publisher]:Publishing:'-90.000000'[INFO][1651094596.822752996][content_filtering_publisher]:Publishing:'-80.000000'[INFO][1651094597.822752475][content_filtering_publisher]:Publishing:'-70.000000'[INFO][1651094598.822721485][content_filtering_publisher]:Publishing:'-60.000000'[INFO][1651094599.822696188][content_filtering_publisher]:Publishing:'-50.000000'[INFO][1651094600.822699217][content_filtering_publisher]:Publishing:'-40.000000'[INFO][1651094601.822744113][content_filtering_publisher]:Publishing:'-30.000000'[INFO][1651094602.822694805][content_filtering_publisher]:Publishing:'-20.000000'[INFO][1651094603.822735805][content_filtering_publisher]:Publishing:'-10.000000'[INFO][1651094604.822722094][content_filtering_publisher]:Publishing:'0.000000'[INFO][1651094605.822699960][content_filtering_publisher]:Publishing:'10.000000'[INFO][1651094606.822748946][content_filtering_publisher]:Publishing:'20.000000'[INFO][1651094607.822694017][content_filtering_publisher]:Publishing:'30.000000'[INFO][1651094608.822708798][content_filtering_publisher]:Publishing:'40.000000'[INFO][1651094609.822692417][content_filtering_publisher]:Publishing:'50.000000'[INFO][1651094610.822696426][content_filtering_publisher]:Publishing:'60.000000'[INFO][1651094611.822751913][content_filtering_publisher]:Publishing:'70.000000'[INFO][1651094612.822692231][content_filtering_publisher]:Publishing:'80.000000'[INFO][1651094613.822745549][content_filtering_publisher]:Publishing:'90.000000'[INFO][1651094614.822701982][content_filtering_publisher]:Publishing:'100.000000'[INFO][1651094615.822691465][content_filtering_publisher]:Publishing:'110.000000'[INFO][1651094616.822649070][content_filtering_publisher]:Publishing:'120.000000'[INFO][1651094617.822693616][content_filtering_publisher]:Publishing:'130.000000'[INFO][1651094618.822691832][content_filtering_publisher]:Publishing:'140.000000'[INFO][1651094619.822688452][content_filtering_publisher]:Publishing:'150.000000'[INFO][1651094620.822645327][content_filtering_publisher]:Publishing:'-100.000000'[INFO][1651094621.822689219][content_filtering_publisher]:Publishing:'-90.000000'[INFO][1651094622.822694292][content_filtering_publisher]:Publishing:'-80.000000'[...] + +Language: unknown +#include"rclcpp/rclcpp.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"rcpputils/join.hpp"#include"std_msgs/msg/float32.hpp"#include"demo_nodes_cpp/visibility_control.h"namespacedemo_nodes_cpp{// Emergency temperature data less than -30 or greater than 100constexprstd::arrayEMERGENCY_TEMPERATURE{-30.0f,100.0f};// Create a ContentFilteringSubscriber class that subclasses the generic rclcpp::Node base class.// The main function below will instantiate the class as a ROS node.classContentFilteringSubscriber:publicrclcpp::Node{public:DEMO_NODES_CPP_PUBLICexplicitContentFilteringSubscriber(constrclcpp::NodeOptions&options):Node("content_filtering_subscriber",options){setvbuf(stdout,NULL,_IONBF,BUFSIZ);// Create a callback function for when messages are received.autocallback=[this](conststd_msgs::msg::Float32&msg)->void{if(msg.dataEMERGENCY_TEMPERATURE[1]){RCLCPP_INFO(this->get_logger(),"I receive an emergency temperature data: [%f]",msg.data);}else{RCLCPP_INFO(this->get_logger(),"I receive a temperature data: [%f]",msg.data);}};// Initialize a subscription with a content filter to receive emergency temperature data that// are less than -30 or greater than 100.rclcpp::SubscriptionOptionssub_options;sub_options.content_filter_options.filter_expression="data < %0 OR data > %1";sub_options.content_filter_options.expression_parameters={std::to_string(EMERGENCY_TEMPERATURE[0]),std::to_string(EMERGENCY_TEMPERATURE[1])};sub_=create_subscription("temperature",10,callback,sub_options);if(!sub_->is_cft_enabled()){RCLCPP_WARN(this->get_logger(),"Content filter is not enabled since it's not supported");}else{RCLCPP_INFO(this->get_logger(),"subscribed to topic\"%s\"with content filter options\"%s, {%s}\"",sub_->get_topic_name(),sub_options.content_filter_options.filter_expression.c_str(),rcpputils::join(sub_options.content_filter_options.expression_parameters,", ").c_str());}}private:rclcpp::Subscription::SharedPtrsub_;};}// namespace demo_nodes_cpp + +Language: unknown +$ros2rundemo_nodes_cppcontent_filtering_subscriber[INFO][1651094590.682660703][content_filtering_subscriber]:subscribedtotopic"/temperature"withcontentfilteroptions"data < %0 OR data > %1, {-30.000000, 100.000000}"[INFO][1651094594.823805294][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-100.000000][INFO][1651094595.823419993][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-90.000000][INFO][1651094596.823410859][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-80.000000][INFO][1651094597.823350377][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-70.000000][INFO][1651094598.823282657][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-60.000000][INFO][1651094599.823297857][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-50.000000][INFO][1651094600.823355597][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-40.000000][INFO][1651094615.823315377][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[110.000000][INFO][1651094616.823258458][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[120.000000][INFO][1651094617.823323525][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[130.000000][INFO][1651094618.823315527][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[140.000000][INFO][1651094619.823331424][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[150.000000][INFO][1651094620.823271748][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-100.000000][INFO][1651094621.823343550][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-90.000000][INFO][1651094622.823286326][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-80.000000][INFO][1651094623.823371031][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-70.000000][INFO][1651094624.823333112][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-60.000000][INFO][1651094625.823266469][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-50.000000][INFO][1651094626.823284093][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-40.000000] + +Language: unknown +$RMW_IMPLEMENTATION=rmw_cyclonedds_cppros2rundemo_nodes_cppcontent_filtering_subscriber[WARN][1651096637.893842072][content_filtering_subscriber]:Contentfilterisnotenabledsinceitisnotsupported[INFO][1651096641.246043703][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-100.000000][INFO][1651096642.245833527][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-90.000000][INFO][1651096643.245743471][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-80.000000][INFO][1651096644.245833932][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-70.000000][INFO][1651096645.245916679][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-60.000000][INFO][1651096646.245861895][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-50.000000][INFO][1651096647.245946352][content_filtering_subscriber]:Ireceiveanemergencytemperaturedata:[-40.000000][INFO][1651096648.245934569][content_filtering_subscriber]:Ireceiveatemperaturedata:[-30.000000][INFO][1651096649.245877906][content_filtering_subscriber]:Ireceiveatemperaturedata:[-20.000000][INFO][1651096650.245939068][content_filtering_subscriber]:Ireceiveatemperaturedata:[-10.000000][INFO][1651096651.245911450][content_filtering_subscriber]:Ireceiveatemperaturedata:[0.000000][INFO][1651096652.245879830][content_filtering_subscriber]:Ireceiveatemperaturedata:[10.000000][INFO][1651096653.245858329][content_filtering_subscriber]:Ireceiveatemperaturedata:[20.000000][INFO][1651096654.245916370][content_filtering_subscriber]:Ireceiveatemperaturedata:[30.000000][INFO][1651096655.245933741][content_filtering_subscriber]:Ireceiveatemperaturedata:[40.000000][INFO][1651096656.245833975][content_filtering_subscriber]:Ireceiveatemperaturedata:[50.000000][INFO][1651096657.245971483][content_filtering_subscriber]:Ireceiveatemperaturedata:[60.000000] diff --git "a/exported_docs/ros2/Creating_a_launch_file\357\203\201.txt" "b/exported_docs/ros2/Creating_a_launch_file\357\203\201.txt" new file mode 100644 index 0000000..8aff575 --- /dev/null +++ "b/exported_docs/ros2/Creating_a_launch_file\357\203\201.txt" @@ -0,0 +1,84 @@ +Title: Creating a launch file +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Launch/Creating-Launch-Files.html +Section: Installation +-------------------------------------------------------------------------------- + +Creating a launch fileGoal:Create a launch file to run a complex ROS 2 system.Tutorial level:IntermediateTime:10 minutesContentsPrerequisitesBackgroundTasks1 Setup2 Write the launch file3 ros2 launch4 Introspect the system with rqt_graphSummaryPrerequisitesThis tutorial uses therqt_graph and turtlesimpackages.You will also need to use a text editor of your preference.As always, don’t forget to source ROS 2 inevery new terminal you open.BackgroundThe launch system in ROS 2 is responsible for helping the user describe the configuration of their system and then execute it as described. +The configuration of the system includes what programs to run, where to run them, what arguments to pass them, and ROS-specific conventions which make it easy to reuse components throughout the system by giving them each a different configuration. +It is also responsible for monitoring the state of the processes launched, and reporting and/or reacting to changes in the state of those processes.Launch files written in Python, XML, or YAML can start and stop different nodes as well as trigger and act on various events. +SeeUsing Python, XML, and YAML for ROS 2 Launch Filesfor a description of the different formats. +The package providing this framework islaunch_ros, which uses the non-ROS-specificlaunchframework underneath.Thedesign documentdetails the goal of the design of ROS 2’s launch system (not all functionality is currently available).Tasks1 SetupCreate a new directory to store your launch files:mkdir launch2 Write the launch fileLet’s put together a ROS 2 launch file using theturtlesimpackage and its executables. +As mentioned above, this can either be in Python, XML, or YAML.PythonXMLYAMLCopy and paste the complete code into thelaunch/turtlesim_mimic_launch.pyfile:fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim'),Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim'),Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtlesim1/turtle1/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])])Copy and paste the complete code into thelaunch/turtlesim_mimic_launch.xmlfile:Copy and paste the complete code into thelaunch/turtlesim_mimic_launch.yamlfile:launch:-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim1"-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim2"-node:pkg:"turtlesim"exec:"mimic"name:"mimic"remap:-from:"/input/pose"to:"/turtlesim1/turtle1/pose"-from:"/output/cmd_vel"to:"/turtlesim2/turtle1/cmd_vel"2.1 Examine the launch fileAll of the launch files above are launching a system of three nodes, all from theturtlesimpackage. +The goal of the system is to launch two turtlesim windows, and have one turtle mimic the movements of the other.When launching the two turtlesim nodes, the only difference between them is their namespace values. +Unique namespaces allow the system to start two nodes without node name or topic name conflicts. +Both turtles in this system receive commands over the same topic and publish their pose over the same topic. +With unique namespaces, messages meant for different turtles can be distinguished.The final node is also from theturtlesimpackage, but a different executable:mimic. +This node has added configuration details in the form of remappings.mimic’s/input/posetopic is remapped to/turtlesim1/turtle1/poseand it’s/output/cmd_veltopic to/turtlesim2/turtle1/cmd_vel. +This meansmimicwill subscribe to/turtlesim1/sim’s pose topic and republish it for/turtlesim2/sim’s velocity command topic to subscribe to. +In other words,turtlesim2will mimicturtlesim1’s movements.PythonXMLYAMLThese import statements pull in some Pythonlaunchmodules.fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodeNext, the launch description itself begins:defgenerate_launch_description():returnLaunchDescription([])The first two actions in the launch description launch the two turtlesim windows:Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim'),Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim'),The final action launches the mimic node with the remaps:Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtlesim1/turtle1/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])The first two actions launch the two turtlesim windows:The final action launches the mimic node with the remaps:The first two actions launch the two turtlesim windows:-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim1"-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim2"The final action launches the mimic node with the remaps:-node:pkg:"turtlesim"exec:"mimic"name:"mimic"remap:-from:"/input/pose"to:"/turtlesim1/turtle1/pose"-from:"/output/cmd_vel"to:"/turtlesim2/turtle1/cmd_vel"3 ros2 launchTo run the launch file created above, enter into the directory you created earlier and run the following command:PythonXMLYAMLcd launchros2 launch turtlesim_mimic_launch.pycd launchros2 launch turtlesim_mimic_launch.xmlcd launchros2 launch turtlesim_mimic_launch.yamlNoteIt is possible to launch a launch file directly (as we do above), or provided by a package. +When it is provided by a package, the syntax is:ros2 launch You learned about creating packages inCreating a package.NoteFor packages with launch files, it is a good idea to add anexec_dependdependency on theros2launchpackage in your package’spackage.xml:ros2launchThis helps make sure that theros2launchcommand is available after building your package. +It also ensures that alllaunch file formatsare recognized.Two turtlesim windows will open, and you will see the following[INFO]messages telling you which nodes your launch file has started:[INFO] [launch]: Default logging verbosity is set to INFO[INFO] [turtlesim_node-1]: process started with pid [11714][INFO] [turtlesim_node-2]: process started with pid [11715][INFO] [mimic-3]: process started with pid [11716]To see the system in action, open a new terminal and run theros2topicpubcommand on the/turtlesim1/turtle1/cmd_veltopic to get the first turtle moving:ros2 topic pub -r 1 /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}"You will see both turtles following the same path.4 Introspect the system with rqt_graphWhile the system is still running, open a new terminal and runrqt_graphto get a better idea of the relationship between the nodes in your launch file.Run the command:rqt_graphA hidden node (theros2topicpubcommand you ran) is publishing data to the/turtlesim1/turtle1/cmd_veltopic on the left, which the/turtlesim1/simnode is subscribed to. +The rest of the graph shows what was described earlier:mimicis subscribed to/turtlesim1/sim’s pose topic, and publishes to/turtlesim2/sim’s velocity command topic.SummaryLaunch files simplify running complex systems with many nodes and specific configuration details. +You can create launch files using Python, XML, or YAML, and run them using theros2launchcommand. + +Code Examples: + +Language: unknown +mkdir launch + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim'),Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim'),Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtlesim1/turtle1/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])]) + +Language: unknown + + +Language: unknown +launch:-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim1"-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim2"-node:pkg:"turtlesim"exec:"mimic"name:"mimic"remap:-from:"/input/pose"to:"/turtlesim1/turtle1/pose"-from:"/output/cmd_vel"to:"/turtlesim2/turtle1/cmd_vel" + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNode + +Language: unknown +defgenerate_launch_description():returnLaunchDescription([]) + +Language: unknown +Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim'),Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim'), + +Language: unknown +Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtlesim1/turtle1/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),]) + +Language: unknown + + +Language: unknown + + +Language: unknown +-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim1"-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim2" + +Language: unknown +-node:pkg:"turtlesim"exec:"mimic"name:"mimic"remap:-from:"/input/pose"to:"/turtlesim1/turtle1/pose"-from:"/output/cmd_vel"to:"/turtlesim2/turtle1/cmd_vel" + +Language: unknown +cd launchros2 launch turtlesim_mimic_launch.py + +Language: unknown +cd launchros2 launch turtlesim_mimic_launch.xml + +Language: unknown +cd launchros2 launch turtlesim_mimic_launch.yaml + +Language: unknown +ros2 launch + +Language: unknown +ros2launch + +Language: unknown +[INFO] [launch]: Default logging verbosity is set to INFO[INFO] [turtlesim_node-1]: process started with pid [11714][INFO] [turtlesim_node-2]: process started with pid [11715][INFO] [mimic-3]: process started with pid [11716] + +Language: unknown +ros2 topic pub -r 1 /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}" + +Language: unknown +rqt_graph diff --git "a/exported_docs/ros2/Creating_a_package\357\203\201.txt" "b/exported_docs/ros2/Creating_a_package\357\203\201.txt" new file mode 100644 index 0000000..cd1100e --- /dev/null +++ "b/exported_docs/ros2/Creating_a_package\357\203\201.txt" @@ -0,0 +1,126 @@ +Title: Creating a package +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Creating-Your-First-ROS2-Package.html +Section: Installation +-------------------------------------------------------------------------------- + +Creating a packageGoal:Create a new package using either CMake or Python, and run its executable.Tutorial level:BeginnerTime:15 minutesContentsBackground1 What is a ROS 2 package?2 What makes up a ROS 2 package?3 Packages in a workspacePrerequisitesTasks1 Create a package2 Build a package3 Source the setup file4 Use the package5 Examine package contents6 Customize package.xmlSummaryNext stepsBackground1 What is a ROS 2 package?A package is an organizational unit for your ROS 2 code. +If you want to be able to install your code or share it with others, then you’ll need it organized in a package. +With packages, you can release your ROS 2 work and allow others to build and use it easily.Package creation in ROS 2 uses ament as its build system and colcon as its build tool. +You can create a package using either CMake or Python, which are officially supported, though other build types do exist.2 What makes up a ROS 2 package?ROS 2 Python and CMake packages each have their own minimum required contents:CMakePythonCMakeLists.txtfile that describes how to build the code within the packageinclude/directory containing the public headers for the packagepackage.xmlfile containing meta information about the packagesrcdirectory containing the source code for the packagepackage.xmlfile containing meta information about the packageresource/marker file for the packagesetup.cfgis required when a package has executables, soros2runcan find themsetup.pycontaining instructions for how to install the package- a directory with the same name as your package, used by ROS 2 tools to find your package, contains__init__.pyThe simplest possible package may have a file structure that looks like:CMakePythonmy_package/CMakeLists.txtinclude/my_package/package.xmlsrc/my_package/package.xmlresource/my_packagesetup.cfgsetup.pymy_package/3 Packages in a workspaceA single workspace can contain as many packages as you want, each in their own folder. +You can also have packages of different build types in one workspace (CMake, Python, etc.). +You cannot have nested packages.Best practice is to have asrcfolder within your workspace, and to create your packages in there. +This keeps the top level of the workspace “clean”.A trivial workspace might look like:workspace_folder/src/cpp_package_1/CMakeLists.txtinclude/cpp_package_1/package.xmlsrc/py_package_1/package.xmlresource/py_package_1setup.cfgsetup.pypy_package_1/...cpp_package_n/CMakeLists.txtinclude/cpp_package_n/package.xmlsrc/PrerequisitesYou should have a ROS 2 workspace after following the instructions in theprevious tutorial. +You will create your package in this workspace.Tasks1 Create a packageFirst,source your ROS 2 installation.Let’s use the workspace you created in theprevious tutorial,ros2_ws, for your new package.Make sure you are in thesrcfolder before running the package creation command.LinuxmacOSWindowscd ~/ros2_ws/srccd ~/ros2_ws/srccd \ros2_ws\srcThe command syntax for creating a new package in ROS 2 is:CMakePythonros2 pkg create --build-type ament_cmake --license Apache-2.0 ros2 pkg create --build-type ament_python --license Apache-2.0 For this tutorial, you will use the optional arguments--node-nameand--license.--node-nameoption creates a simple Hello World type executable in the package, and--licensedeclares the license information for the package.Enter the following command in your terminal:CMakePythonros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name my_node my_packageros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_node my_packageYou will now have a new folder within your workspace’ssrcdirectory calledmy_package.After running the command, your terminal will return the message:CMakePythongoing to create a new packagepackage name: my_packagedestination directory: /home/user/ros2_ws/srcpackage format: 3version: 0.0.0description: TODO: Package descriptionmaintainer: [' ']licenses: ['Apache-2.0']build type: ament_cmakedependencies: []node_name: my_nodecreating folder ./my_packagecreating ./my_package/package.xmlcreating source and include foldercreating folder ./my_package/srccreating folder ./my_package/include/my_packagecreating ./my_package/CMakeLists.txtcreating ./my_package/src/my_node.cppgoing to create a new packagepackage name: my_packagedestination directory: /home/user/ros2_ws/srcpackage format: 3version: 0.0.0description: TODO: Package descriptionmaintainer: [' ']licenses: ['Apache-2.0']build type: ament_pythondependencies: []node_name: my_nodecreating folder ./my_packagecreating ./my_package/package.xmlcreating source foldercreating folder ./my_package/my_packagecreating ./my_package/setup.pycreating ./my_package/setup.cfgcreating folder ./my_package/resourcecreating ./my_package/resource/my_packagecreating ./my_package/my_package/__init__.pycreating folder ./my_package/testcreating ./my_package/test/test_copyright.pycreating ./my_package/test/test_flake8.pycreating ./my_package/test/test_pep257.pycreating ./my_package/my_package/my_node.pyYou can see the automatically generated files for the new package.2 Build a packagePutting packages in a workspace is especially valuable because you can build many packages at once by runningcolconbuildin the workspace root. +Otherwise, you would have to build each package individually.Return to the root of your workspace:LinuxmacOSWindowscd ~/ros2_wscd ~/ros2_wscd \ros2_wsNow you can build your packages:LinuxmacOSWindowscolcon buildcolcon buildcolcon build --merge-installWindows doesn’t allow long paths, somerge-installwill combine all the paths into theinstalldirectory.Recall from the last tutorial that you also have theros_tutorialspackages in yourros2_ws. +You might have noticed that runningcolconbuildalso built theturtlesimpackage. +That’s fine when you only have a few packages in your workspace, but when there are many packages,colconbuildcan take a long time.To build only themy_packagepackage next time, you can run:colcon build --packages-select my_package3 Source the setup fileTo use your new package and executable, first open a new terminal and source your main ROS 2 installation.Then, from inside theros2_wsdirectory, run the following command to source your workspace:LinuxmacOSWindowssource install/local_setup.bash. install/local_setup.bashcall install/local_setup.batNow that your workspace has been added to your path, you will be able to use your new package’s executables.4 Use the packageTo run the executable you created using the--node-nameargument during package creation, enter the command:ros2 run my_package my_nodeWhich will return a message to your terminal:CMakePythonhello world my_package packageHi from my_package.5 Examine package contentsInsideros2_ws/src/my_package, you will see the files and folders thatros2pkgcreateautomatically generated:CMakePythonCMakeLists.txt include package.xml srcmy_node.cppis inside thesrcdirectory. +This is where all your custom C++ nodes will go in the future.my_package package.xml resource setup.cfg setup.py testmy_node.pyis inside themy_packagedirectory. +This is where all your custom Python nodes will go in the future.6 Customize package.xmlYou may have noticed in the return message after creating your package that the fieldsdescriptionandlicensecontainTODOnotes. +That’s because the package description and license declaration are not automatically set, but are required if you ever want to release your package. +Themaintainerfield may also need to be filled in.Fromros2_ws/src/my_package, openpackage.xmlusing your preferred text editor:CMakePythonmy_package0.0.0TODO:PackagedescriptionuserTODO:Licensedeclarationament_cmakeament_lint_autoament_lint_commonament_cmakemy_package0.0.0TODO:PackagedescriptionuserTODO:Licensedeclarationament_copyrightament_flake8ament_pep257python3-pytestament_pythonInput your name and email on themaintainerline if it hasn’t been automatically populated for you. +Then, edit thedescriptionline to summarize the package:BeginnerclientlibrariestutorialspracticepackageThen, update thelicenseline. +You can read more about open source licenseshere. +Since this package is only for practice, it’s safe to use any license. +We’ll useApache-2.0:Apache-2.0Don’t forget to save once you’re done editing.Below the license tag, you will see some tag names ending with_depend. +This is where yourpackage.xmlwould list its dependencies on other packages, for colcon to search for.my_packageis simple and doesn’t have any dependencies, but you will see this space being utilized in upcoming tutorials.CMakePythonYou’re all done for now!Thesetup.pyfile contains the same description, maintainer and license fields aspackage.xml, so you need to set those as well. +They need to match exactly in both files. +The version and name (package_name) also need to match exactly, and should be automatically populated in both files.Opensetup.pywith your preferred text editor.fromsetuptoolsimportfind_packages,setuppackage_name='my_py_pkg'setup(name=package_name,version='0.0.0',packages=find_packages(exclude=['test']),data_files=[('share/ament_index/resource_index/packages',['resource/'+package_name]),('share/'+package_name,['package.xml']),],install_requires=['setuptools'],zip_safe=True,maintainer='TODO',maintainer_email='TODO',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts':['my_node = my_py_pkg.my_node:main'],},)Edit themaintainer,maintainer_email, anddescriptionlines to matchpackage.xml.Don’t forget to save the file.SummaryYou’ve created a package to organize your code and make it easy to use for others.Your package was automatically populated with the necessary files, and then you used colcon to build it so you can use its executables in your local environment.Next stepsNext, let’s add something meaningful to a package. +You’ll start with a simple publisher/subscriber system, which you can choose to write in eitherC++orPython. + +Code Examples: + +Language: unknown +my_package/CMakeLists.txtinclude/my_package/package.xmlsrc/ + +Language: unknown +my_package/package.xmlresource/my_packagesetup.cfgsetup.pymy_package/ + +Language: unknown +workspace_folder/src/cpp_package_1/CMakeLists.txtinclude/cpp_package_1/package.xmlsrc/py_package_1/package.xmlresource/py_package_1setup.cfgsetup.pypy_package_1/...cpp_package_n/CMakeLists.txtinclude/cpp_package_n/package.xmlsrc/ + +Language: unknown +cd ~/ros2_ws/src + +Language: unknown +cd ~/ros2_ws/src + +Language: unknown +cd \ros2_ws\src + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name my_node my_package + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_node my_package + +Language: unknown +going to create a new packagepackage name: my_packagedestination directory: /home/user/ros2_ws/srcpackage format: 3version: 0.0.0description: TODO: Package descriptionmaintainer: [' ']licenses: ['Apache-2.0']build type: ament_cmakedependencies: []node_name: my_nodecreating folder ./my_packagecreating ./my_package/package.xmlcreating source and include foldercreating folder ./my_package/srccreating folder ./my_package/include/my_packagecreating ./my_package/CMakeLists.txtcreating ./my_package/src/my_node.cpp + +Language: unknown +going to create a new packagepackage name: my_packagedestination directory: /home/user/ros2_ws/srcpackage format: 3version: 0.0.0description: TODO: Package descriptionmaintainer: [' ']licenses: ['Apache-2.0']build type: ament_pythondependencies: []node_name: my_nodecreating folder ./my_packagecreating ./my_package/package.xmlcreating source foldercreating folder ./my_package/my_packagecreating ./my_package/setup.pycreating ./my_package/setup.cfgcreating folder ./my_package/resourcecreating ./my_package/resource/my_packagecreating ./my_package/my_package/__init__.pycreating folder ./my_package/testcreating ./my_package/test/test_copyright.pycreating ./my_package/test/test_flake8.pycreating ./my_package/test/test_pep257.pycreating ./my_package/my_package/my_node.py + +Language: unknown +cd ~/ros2_ws + +Language: unknown +cd ~/ros2_ws + +Language: unknown +cd \ros2_ws + +Language: unknown +colcon build + +Language: unknown +colcon build + +Language: unknown +colcon build --merge-install + +Language: unknown +colcon build --packages-select my_package + +Language: unknown +source install/local_setup.bash + +Language: unknown +. install/local_setup.bash + +Language: unknown +call install/local_setup.bat + +Language: unknown +ros2 run my_package my_node + +Language: unknown +hello world my_package package + +Language: unknown +Hi from my_package. + +Language: unknown +CMakeLists.txt include package.xml src + +Language: unknown +my_package package.xml resource setup.cfg setup.py test + +Language: unknown +my_package0.0.0TODO:PackagedescriptionuserTODO:Licensedeclarationament_cmakeament_lint_autoament_lint_commonament_cmake + +Language: unknown +my_package0.0.0TODO:PackagedescriptionuserTODO:Licensedeclarationament_copyrightament_flake8ament_pep257python3-pytestament_python + +Language: unknown +Beginnerclientlibrariestutorialspracticepackage + +Language: unknown +Apache-2.0 + +Language: unknown +fromsetuptoolsimportfind_packages,setuppackage_name='my_py_pkg'setup(name=package_name,version='0.0.0',packages=find_packages(exclude=['test']),data_files=[('share/ament_index/resource_index/packages',['resource/'+package_name]),('share/'+package_name,['package.xml']),],install_requires=['setuptools'],zip_safe=True,maintainer='TODO',maintainer_email='TODO',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts':['my_node = my_py_pkg.my_node:main'],},) diff --git "a/exported_docs/ros2/Creating_a_workspace\357\203\201.txt" "b/exported_docs/ros2/Creating_a_workspace\357\203\201.txt" new file mode 100644 index 0000000..1a292d8 --- /dev/null +++ "b/exported_docs/ros2/Creating_a_workspace\357\203\201.txt" @@ -0,0 +1,120 @@ +Title: Creating a workspace +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Creating-A-Workspace/Creating-A-Workspace.html +Section: Installation +-------------------------------------------------------------------------------- + +Creating a workspaceGoal:Create a workspace and learn how to set up an overlay for development and testing.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Source ROS 2 environment2 Create a new directory3 Clone a sample repo4 Resolve dependencies5 Build the workspace with colcon6 Source the overlay7 Modify the overlaySummaryNext stepsBackgroundA workspace is a directory containing ROS 2 packages. +Before using ROS 2, it’s necessary to source your ROS 2 installation workspace in the terminal you plan to work in. +This makes ROS 2’s packages available for you to use in that terminal.You also have the option of sourcing an “overlay” - a secondary workspace where you can add new packages without interfering with the existing ROS 2 workspace that you’re extending, or “underlay”. +Your underlay must contain the dependencies of all the packages in your overlay. +Packages in your overlay will override packages in the underlay. +It’s also possible to have several layers of underlays and overlays, with each successive overlay using the packages of its parent underlays.PrerequisitesROS 2 installationcolcon installationgit installationturtlesim installationHaverosdep installedUnderstanding of basic terminal commands (here’s a guide for Linux)Text editor of your choiceTasks1 Source ROS 2 environmentYour main ROS 2 installation will be your underlay for this tutorial. +(Keep in mind that an underlay does not necessarily have to be the main ROS 2 installation.)Depending on how you installed ROS 2 (from source or binaries), and which platform you’re on, your exact source command will vary:LinuxmacOSWindowssource /opt/ros/jazzy/setup.bash. ~/ros2_install/ros2-osx/setup.bashRemember to use ax64NativeToolsCommandPromptforVS2019for executing the following commands, as we are going to build a workspace.call C:\dev\ros2\local_setup.batConsult theinstallation guideyou followed if these commands don’t work for you.2 Create a new directoryBest practice is to create a new directory for every new workspace. +The name doesn’t matter, but it is helpful to have it indicate the purpose of the workspace. +Let’s choose the directory nameros2_ws, for “development workspace”:LinuxmacOSWindowsmkdir -p ~/ros2_ws/srccd ~/ros2_ws/srcmkdir -p ~/ros2_ws/srccd ~/ros2_ws/srcmd \ros2_ws\srccd \ros2_ws\srcAnother best practice is to put any packages in your workspace into thesrcdirectory. +The above code creates asrcdirectory insideros2_wsand then navigates into it.3 Clone a sample repoEnsure you’re still in theros2_ws/srcdirectory before you clone.In the rest of the beginner developer tutorials, you will create your own packages, but for now you will practice putting a workspace together using existing packages.If you went through theBeginner: CLI Toolstutorials, you’ll be familiar withturtlesim, one of the packages inros_tutorials.A repo can have multiple branches. +You need to check out the one that targets your installed ROS 2 distro. +When you clone this repo, add the-bargument followed by that branch.In theros2_ws/srcdirectory, run the following command:git clone https://github.com/ros/ros_tutorials.git -b jazzyNowros_tutorialsis cloned in your workspace. Theros_tutorialsrepository contains theturtlesimpackage, which we’ll use in the rest of this tutorial. The other packages in this repository are not built because they contain aCOLCON_IGNOREfile.So far you have populated your workspace with a sample package, but it isn’t a fully-functional workspace yet. +You need to resolve the dependencies first and then build the workspace.4 Resolve dependenciesBefore building the workspace, you need to resolve the package dependencies. +You may have all the dependencies already, but best practice is to check for dependencies every time you clone. +You wouldn’t want a build to fail after a long wait only to realize that you have missing dependencies.From the root of your workspace (ros2_ws), run the following command:LinuxmacOSWindows# cd if you're still in the ``src`` directory with the ``ros_tutorials`` clonecd.. +rosdepinstall-i--from-pathsrc--rosdistrojazzy-yrosdep only runs on Linux, so you can skip ahead to section “5 Build the workspace with colcon”.rosdep only runs on Linux, so you can skip ahead to section “5 Build the workspace with colcon”.If you installed ROS 2 on Linux from source or the binary archive, you will need to use the rosdep command from their installation instructions. +Here are thefrom-source rosdep sectionand thebinary archive rosdep section.If you already have all your dependencies, the console will return:#AllrequiredrosdepsinstalledsuccessfullyPackages declare their dependencies in the package.xml file (you will learn more about packages in the next tutorial). +This command walks through those declarations and installs the ones that are missing. +You can learn more aboutrosdepin another tutorial (coming soon).5 Build the workspace with colconFrom the root of your workspace (ros2_ws), you can now build your packages using the command:LinuxmacOSWindowscolcon buildcolcon buildcolcon build --merge-installWindows doesn’t allow long paths, somerge-installwill combine all the paths into theinstalldirectory.The console will return the following message:Starting >>> turtlesimFinished <<< turtlesim [5.49s]Summary: 1 package finished [5.58s]NoteOther useful arguments forcolconbuild:--packages-up-tobuilds the package you want, plus all its dependencies, but not the whole workspace (saves time)--symlink-installsaves you from having to rebuild every time you tweak python scripts--event-handlersconsole_direct+shows console output while building (can otherwise be found in thelogdirectory)--executorsequentialprocesses the packages one by one instead of using parallelismOnce the build is finished, enter the command in the workspace root (~/ros2_ws):LinuxmacOSWindowslslsdirAnd you will see that colcon has created new directories:build install log srcTheinstalldirectory is where your workspace’s setup files are, which you can use to source your overlay.6 Source the overlayBefore sourcing the overlay, it is very important that you open a new terminal, separate from the one where you built the workspace. +Sourcing an overlay in the same terminal where you built, or likewise building where an overlay is sourced, may create complex issues.In the new terminal, source your main ROS 2 environment as the “underlay”, so you can build the overlay “on top of” it:LinuxmacOSWindowssource /opt/ros/jazzy/setup.bash. ~/ros2_install/ros2-osx/setup.bashIn this case you can use a normal command prompt, as we are not going to build any workspace in this terminal.call C:\dev\ros2\local_setup.batGo into the root of your workspace:LinuxmacOSWindowscd ~/ros2_wscd ~/ros2_wscd \ros2_wsIn the root, source your overlay:LinuxmacOSWindowssource install/local_setup.bash. install/local_setup.bashcall install\setup.batNoteSourcing thelocal_setupof the overlay will only add the packages available in the overlay to your environment.setupsources the overlay as well as the underlay it was created in, allowing you to utilize both workspaces.So, sourcing your main ROS 2 installation’ssetupand then theros2_wsoverlay’slocal_setup, like you just did, +is the same as just sourcingros2_ws’ssetup, because that includes the environment of its underlay.Now you can run theturtlesimpackage from the overlay:ros2 run turtlesim turtlesim_nodeBut how can you tell that this is the overlay turtlesim running, and not your main installation’s turtlesim?Let’s modify turtlesim in the overlay so you can see the effects:You can modify and rebuild packages in the overlay separately from the underlay.The overlay takes precedence over the underlay.7 Modify the overlayYou can modifyturtlesimin your overlay by editing the title bar on the turtlesim window. +To do this, locate theturtle_frame.cppfile in~/ros2_ws/src/ros_tutorials/turtlesim/src. +Openturtle_frame.cppwith your preferred text editor.Find the functionsetWindowTitle("TurtleSim");, change the value"TurtleSim"to"MyTurtleSim", and save the file.Return to the first terminal where you rancolconbuildearlier and run it again.Return to the second terminal (where the overlay is sourced) and run turtlesim again:ros2 run turtlesim turtlesim_nodeYou will see the title bar on the turtlesim window now says “MyTurtleSim”.Even though your main ROS 2 environment was sourced in this terminal earlier, the overlay of yourros2_wsenvironment takes precedence over the contents of the underlay.To see that your underlay is still intact, open a brand new terminal and source only your ROS 2 installation. +Run turtlesim again:ros2 run turtlesim turtlesim_nodeYou can see that modifications in the overlay did not actually affect anything in the underlay.SummaryIn this tutorial, you sourced your main ROS 2 distro install as your underlay, and created an overlay by cloning and building packages in a new workspace. +The overlay gets prepended to the path, and takes precedence over the underlay, as you saw with your modified turtlesim.Using overlays is recommended for working on a small number of packages, so you don’t have to put everything in the same workspace and rebuild a huge workspace on every iteration.Next stepsNow that you understand the details behind creating, building and sourcing your own workspace, you can learn how tocreate your own packages. + +Code Examples: + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +. ~/ros2_install/ros2-osx/setup.bash + +Language: unknown +call C:\dev\ros2\local_setup.bat + +Language: unknown +mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src + +Language: unknown +mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src + +Language: unknown +md \ros2_ws\srccd \ros2_ws\src + +Language: unknown +git clone https://github.com/ros/ros_tutorials.git -b jazzy + +Language: unknown +# cd if you're still in the ``src`` directory with the ``ros_tutorials`` clonecd.. +rosdepinstall-i--from-pathsrc--rosdistrojazzy-y + +Language: unknown +#Allrequiredrosdepsinstalledsuccessfully + +Language: unknown +colcon build + +Language: unknown +colcon build + +Language: unknown +colcon build --merge-install + +Language: unknown +Starting >>> turtlesimFinished <<< turtlesim [5.49s]Summary: 1 package finished [5.58s] + +Language: unknown +ls + +Language: unknown +ls + +Language: unknown +dir + +Language: unknown +build install log src + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +. ~/ros2_install/ros2-osx/setup.bash + +Language: unknown +call C:\dev\ros2\local_setup.bat + +Language: unknown +cd ~/ros2_ws + +Language: unknown +cd ~/ros2_ws + +Language: unknown +cd \ros2_ws + +Language: unknown +source install/local_setup.bash + +Language: unknown +. install/local_setup.bash + +Language: unknown +call install\setup.bat + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtlesim_node diff --git "a/exported_docs/ros2/Creating_an_action\357\203\201.txt" "b/exported_docs/ros2/Creating_an_action\357\203\201.txt" new file mode 100644 index 0000000..e1e7988 --- /dev/null +++ "b/exported_docs/ros2/Creating_an_action\357\203\201.txt" @@ -0,0 +1,73 @@ +Title: Creating an action +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Creating-an-Action.html +Section: Installation +-------------------------------------------------------------------------------- + +Creating an actionGoal:Define an action in a ROS 2 package.Tutorial level:IntermediateTime:5 minutesContentsBackgroundPrerequisitesTasks1 Creating an interface package2 Defining an action3 Building an actionSummaryNext stepsRelated contentBackgroundYou learned about actions previously in theUnderstanding actionstutorial. +Like the other communication types and their respective interfaces (topics/msg and services/srv), +you can also custom-define actions in your packages. +This tutorial shows you how to define and build an action that you can use +with the action server and action client you will write in the next tutorial.PrerequisitesYou should haveROS 2andcolconinstalled.You should know how to set up aworkspaceand create packages.Remember tosource your ROS 2 installationfirst.Tasks1 Creating an interface packageLinuxmacOSWindowsmkdir-p~/ros2_ws/src# you can reuse an existing workspace with this naming conventioncd~/ros2_ws/src +ros2pkgcreate--licenseApache-2.0custom_action_interfacesmkdir-p~/ros2_ws/srccd~/ros2_ws/src +ros2pkgcreate--licenseApache-2.0custom_action_interfacesmd\ros2_ws\srccd\ros2_ws\src +ros2pkgcreate--licenseApache-2.0custom_action_interfaces2 Defining an actionActions are defined in.actionfiles of the form:# Request---# Result---# FeedbackAn action definition is made up of three message definitions separated by---.Arequestmessage is sent from an action client to an action server initiating a new goal.Aresultmessage is sent from an action server to an action client when a goal is done.Feedbackmessages are periodically sent from an action server to an action client with updates about a goal.An instance of an action is typically referred to as agoal.Say we want to define a new action “Fibonacci” for computing theFibonacci sequence.Create anactiondirectory in our ROS 2 packagecustom_action_interfaces:LinuxmacOSWindowscdcustom_action_interfaces +mkdiractioncdcustom_action_interfaces +mkdiractioncdcustom_action_interfaces +mdactionWithin theactiondirectory, create a file calledFibonacci.actionwith the following contents:int32 order---int32[] sequence---int32[] partial_sequenceThe goal request is theorderof the Fibonacci sequence we want to compute, the result is the finalsequence, and the feedback is thepartial_sequencecomputed so far.3 Building an actionBefore we can use the new Fibonacci action type in our code, we must pass the definition to the rosidl code generation pipeline.This is accomplished by adding the following lines to ourCMakeLists.txtbefore theament_package()line:find_package(rosidl_default_generatorsREQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}"action/Fibonacci.action")We should also add the required dependencies to ourpackage.xml:rosidl_default_generatorsrosidl_interface_packagesWe should now be able to build the package containing theFibonacciaction definition:# Change to the root of the workspacecd~/ros2_ws# BuildcolconbuildWe’re done!By convention, action types will be prefixed by their package name and the wordaction. +So when we want to refer to our new action, it will have the full namecustom_action_interfaces/action/Fibonacci.We can check that our action built successfully with the command line tool. +First source our workspace:LinuxmacOSWindowssourceinstall/local_setup.bashsourceinstall/local_setup.bashcallinstall\local_setup.batNow check that our action definition exists:ros2interfaceshowcustom_action_interfaces/action/FibonacciYou should see the Fibonacci action definition printed to the screen.SummaryIn this tutorial, you learned the structure of an action definition. +You also learned how to correctly build a new action interface usingCMakeLists.txtandpackage.xml, +and how to verify a successful build.Next stepsNext, let’s utilize your newly defined action interface by creating an action service and client (inPythonorC++).Related contentFor more detailed information about ROS actions, please refer to thedesign article. + +Code Examples: + +Language: unknown +mkdir-p~/ros2_ws/src# you can reuse an existing workspace with this naming conventioncd~/ros2_ws/src +ros2pkgcreate--licenseApache-2.0custom_action_interfaces + +Language: unknown +mkdir-p~/ros2_ws/srccd~/ros2_ws/src +ros2pkgcreate--licenseApache-2.0custom_action_interfaces + +Language: unknown +md\ros2_ws\srccd\ros2_ws\src +ros2pkgcreate--licenseApache-2.0custom_action_interfaces + +Language: unknown +# Request---# Result---# Feedback + +Language: unknown +cdcustom_action_interfaces +mkdiraction + +Language: unknown +cdcustom_action_interfaces +mkdiraction + +Language: unknown +cdcustom_action_interfaces +mdaction + +Language: unknown +int32 order---int32[] sequence---int32[] partial_sequence + +Language: unknown +find_package(rosidl_default_generatorsREQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}"action/Fibonacci.action") + +Language: unknown +rosidl_default_generatorsrosidl_interface_packages + +Language: unknown +# Change to the root of the workspacecd~/ros2_ws# Buildcolconbuild + +Language: unknown +sourceinstall/local_setup.bash + +Language: unknown +sourceinstall/local_setup.bash + +Language: unknown +callinstall\local_setup.bat + +Language: unknown +ros2interfaceshowcustom_action_interfaces/action/Fibonacci diff --git "a/exported_docs/ros2/Creating_and_using_plugins_(C++)\357\203\201.txt" "b/exported_docs/ros2/Creating_and_using_plugins_(C++)\357\203\201.txt" new file mode 100644 index 0000000..4fd5877 --- /dev/null +++ "b/exported_docs/ros2/Creating_and_using_plugins_(C++)\357\203\201.txt" @@ -0,0 +1,74 @@ +Title: Creating and using plugins (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Pluginlib.html +Section: Installation +-------------------------------------------------------------------------------- + +Creating and using plugins (C++)Goal:Learn to create and load a simple plugin usingpluginlib.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create the Base Class Package2 Create the Plugin Package2.1 Source code for the plugins2.2 Plugin Declaration XML2.3 CMake Plugin Declaration3 Use the Plugins4 Build and runSummaryBackgroundThis tutorial is derived fromhttp://wiki.ros.org/pluginlibandWriting and Using a Simple Plugin Tutorial.pluginlibis a C++ library for loading and unloading plugins from within a ROS package. +Plugins are dynamically loadable classes that are loaded from a runtime library (i.e. shared object, dynamically linked library). +With pluginlib, you do not have to explicitly link your application against the library containing the classes – insteadpluginlibcan open a library containing exported classes at any point without the application having any prior awareness of the library or the header file containing the class definition. +Plugins are useful for extending/modifying application behavior without needing the application source code.PrerequisitesThis tutorial assumes basic C++ knowledge and that you have successfullyinstalled ROS 2.TasksIn this tutorial, you will create two new packages, one that defines the base class, and another that provides the plugins. +The base class will define a generic polygon class, and then our plugins will define specific shapes.1 Create the Base Class PackageCreate a new empty package in yourros2_ws/srcfolder with the following command:ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies pluginlib --node-name area_node polygon_baseOpen your favorite editor, editros2_ws/src/polygon_base/include/polygon_base/regular_polygon.hpp, and paste the following inside of it:#ifndef POLYGON_BASE_REGULAR_POLYGON_HPP#define POLYGON_BASE_REGULAR_POLYGON_HPPnamespacepolygon_base{classRegularPolygon{public:virtualvoidinitialize(doubleside_length)=0;virtualdoublearea()=0;virtual~RegularPolygon(){}protected:RegularPolygon(){}};}// namespace polygon_base#endif// POLYGON_BASE_REGULAR_POLYGON_HPPThe code above creates an abstract class calledRegularPolygon. +One thing to notice is the presence of the initialize method. +Withpluginlib, a constructor without parameters is required, so if any parameters to the class are needed, we use the initialize method to pass them to the object.We need to make this header available to other classes, so openros2_ws/src/polygon_base/CMakeLists.txtfor editing. +Add the following lines after theament_target_dependenciescommand:install(DIRECTORYinclude/DESTINATIONinclude)And add this command before theament_packagecommand:ament_export_include_directories(include)We will return to this package later to write our test node.2 Create the Plugin PackageNow we’re going to write two non-virtual implementations of our abstract class. +Create a second empty package in yourros2_ws/srcfolder with the following command:ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies polygon_base pluginlib --library-name polygon_plugins polygon_plugins2.1 Source code for the pluginsOpenros2_ws/src/polygon_plugins/src/polygon_plugins.cppfor editing, and paste the following inside of it:#include#includenamespacepolygon_plugins{classSquare:publicpolygon_base::RegularPolygon{public:voidinitialize(doubleside_length)override{side_length_=side_length;}doublearea()override{returnside_length_*side_length_;}protected:doubleside_length_;};classTriangle:publicpolygon_base::RegularPolygon{public:voidinitialize(doubleside_length)override{side_length_=side_length;}doublearea()override{return0.5*side_length_*getHeight();}doublegetHeight(){returnsqrt((side_length_*side_length_)-((side_length_/2)*(side_length_/2)));}protected:doubleside_length_;};}#includePLUGINLIB_EXPORT_CLASS(polygon_plugins::Square,polygon_base::RegularPolygon)PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle,polygon_base::RegularPolygon)The implementation of the Square and Triangle classes is fairly straightforward: save the side length, and use it to calculate the area. +The only piece that is pluginlib specific is the last three lines, which invokes some magical macros that register the classes as actual plugins. +Let’s go through the arguments to thePLUGINLIB_EXPORT_CLASSmacro:The fully-qualified type of the plugin class, in this case,polygon_plugins::Square.The fully-qualified type of the base class, in this case,polygon_base::RegularPolygon.2.2 Plugin Declaration XMLThe steps above enable plugin instances to be created when the containing library is loaded, but the plugin loader still needs a way to find that library and to know what to reference within that library. +To this end, we’ll also create an XML file that, along with a special export line in the package manifest, makes all the necessary information about our plugins available to the ROS toolchain.Createros2_ws/src/polygon_plugins/plugins.xmlwith the following code:Thisisasquareplugin.Thisisatriangleplugin.A couple things to note:Thelibrarytag gives the relative path to a library that contains the plugins that we want to export. +In ROS 2, that is just the name of the library. In ROS 1, it contained the prefixlibor sometimeslib/lib(i.e.lib/libpolygon_plugins), but here it is simpler.Theclasstag declares a plugin that we want to export from our library. +Let’s go through its parameters:type: The fully qualified type of the plugin. For us, that’spolygon_plugins::Square.base_class: The fully qualified base class type for the plugin. For us, that’spolygon_base::RegularPolygon.description: A description of the plugin and what it does.2.3 CMake Plugin DeclarationThe last step is to export your plugins viaCMakeLists.txt. +This is a change from ROS 1, where the exporting was done viapackage.xml. +Add the following line to yourros2_ws/src/polygon_plugins/CMakeLists.txtafter the line readingfind_package(pluginlibREQUIRED):pluginlib_export_plugin_description_file(polygon_baseplugins.xml)The arguments to thepluginlib_export_plugin_description_filecommand are:The package with the base class, i.e.polygon_base.The relative path to the Plugin Declaration xml, i.e.plugins.xml.3 Use the PluginsNow it’s time to use the plugins. +This can be done in any package, but here we’re going to do it in the base package. +Editros2_ws/src/polygon_base/src/area_node.cppto contain the following:#include#includeintmain(intargc,char**argv){// To avoid unused parameter warnings(void)argc;(void)argv;pluginlib::ClassLoaderpoly_loader("polygon_base","polygon_base::RegularPolygon");try{std::shared_ptrtriangle=poly_loader.createSharedInstance("polygon_plugins::Triangle");triangle->initialize(10.0);std::shared_ptrsquare=poly_loader.createSharedInstance("polygon_plugins::Square");square->initialize(10.0);printf("Triangle area: %.2f\n",triangle->area());printf("Square area: %.2f\n",square->area());}catch(pluginlib::PluginlibException&ex){printf("The plugin failed to load for some reason. Error: %s\n",ex.what());}return0;}TheClassLoaderis the key class to understand, defined in theclass_loader.hppheader file:It is templated with the base class, i.e.polygon_base::RegularPolygon.The first argument is a string for the package name of the base class, i.e.polygon_base.The second argument is a string with the fully qualified base class type for the plugin, i.e.polygon_base::RegularPolygon.There are a number of ways to instantiate an instance of the class. +In this example, we’re using shared pointers. +We just need to callcreateSharedInstancewith the fully-qualified type of the plugin class, in this case,polygon_plugins::Square.Important note: thepolygon_basepackage in which this node is defined does NOT depend on thepolygon_pluginsclass. +The plugins will be loaded dynamically without any dependency needing to be declared. +Furthermore, we’re instantiating the classes with hardcoded plugin names, but you can also do so dynamically with parameters, etc.4 Build and runNavigate back to the root of your workspace,ros2_ws, and build your new packages:colcon build --packages-select polygon_base polygon_pluginsFromros2_ws, be sure to source the setup files:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the node:ros2 run polygon_base area_nodeIt should print:Triangle area: 43.30Square area: 100.00SummaryCongratulations! You’ve just written and used your first plugins. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies pluginlib --node-name area_node polygon_base + +Language: unknown +#ifndef POLYGON_BASE_REGULAR_POLYGON_HPP#define POLYGON_BASE_REGULAR_POLYGON_HPPnamespacepolygon_base{classRegularPolygon{public:virtualvoidinitialize(doubleside_length)=0;virtualdoublearea()=0;virtual~RegularPolygon(){}protected:RegularPolygon(){}};}// namespace polygon_base#endif// POLYGON_BASE_REGULAR_POLYGON_HPP + +Language: unknown +install(DIRECTORYinclude/DESTINATIONinclude) + +Language: unknown +ament_export_include_directories(include) + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies polygon_base pluginlib --library-name polygon_plugins polygon_plugins + +Language: unknown +#include#includenamespacepolygon_plugins{classSquare:publicpolygon_base::RegularPolygon{public:voidinitialize(doubleside_length)override{side_length_=side_length;}doublearea()override{returnside_length_*side_length_;}protected:doubleside_length_;};classTriangle:publicpolygon_base::RegularPolygon{public:voidinitialize(doubleside_length)override{side_length_=side_length;}doublearea()override{return0.5*side_length_*getHeight();}doublegetHeight(){returnsqrt((side_length_*side_length_)-((side_length_/2)*(side_length_/2)));}protected:doubleside_length_;};}#includePLUGINLIB_EXPORT_CLASS(polygon_plugins::Square,polygon_base::RegularPolygon)PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle,polygon_base::RegularPolygon) + +Language: unknown +Thisisasquareplugin.Thisisatriangleplugin. + +Language: unknown +pluginlib_export_plugin_description_file(polygon_baseplugins.xml) + +Language: unknown +#include#includeintmain(intargc,char**argv){// To avoid unused parameter warnings(void)argc;(void)argv;pluginlib::ClassLoaderpoly_loader("polygon_base","polygon_base::RegularPolygon");try{std::shared_ptrtriangle=poly_loader.createSharedInstance("polygon_plugins::Triangle");triangle->initialize(10.0);std::shared_ptrsquare=poly_loader.createSharedInstance("polygon_plugins::Square");square->initialize(10.0);printf("Triangle area: %.2f\n",triangle->area());printf("Square area: %.2f\n",square->area());}catch(pluginlib::PluginlibException&ex){printf("The plugin failed to load for some reason. Error: %s\n",ex.what());}return0;} + +Language: unknown +colcon build --packages-select polygon_base polygon_plugins + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run polygon_base area_node + +Language: unknown +Triangle area: 43.30Square area: 100.00 diff --git "a/exported_docs/ros2/Cross-compilation\357\203\201.txt" "b/exported_docs/ros2/Cross-compilation\357\203\201.txt" new file mode 100644 index 0000000..cdfdc18 --- /dev/null +++ "b/exported_docs/ros2/Cross-compilation\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Cross-compilation +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Cross-Compilation.html +Section: Installation +-------------------------------------------------------------------------------- + +Cross-compilationTable of ContentsOverviewHow does it work ?AlternativesOverviewOpen Robotics provides pre-built ROS 2 packages for multiple platforms, but a number of developers still rely oncross-compilationfor different reasons such as:The development machine does not match the target system.Tuning the build for specific core architecture (e.g. setting -mcpu=cortex-a53 -mfpu=neon-fp-armv8 when building for Raspberry Pi3).Targeting a file system other than the ones supported by the pre-built images released by Open Robotics.How does it work ?Cross-compiling simple software (e.g. no dependencies on external libraries) is relatively simple and only requiring a cross-compiler toolchain to be used instead of the native toolchain.There are a number of factors which make this process more complex:The software being built must support the target architecture. Architecture specific code must be properly isolated and enabled during the build according to the target architecture. Examples include assembly code.All dependencies (e.g. libraries) must be present, either as pre-built or cross-compiled packages, before the target software using them is cross-compiled.When building software stacks (as opposed to standalone software) using build tools (e.g. colcon), it is expected that the build tool provides a mechanism to allow the developer to enable cross-compilation on the underlying build system used by each piece of software in the stack.AlternativesAn alternative to cross-compilation is tobuild multi-platform Docker imagesusingdockerbuildx. \ No newline at end of file diff --git "a/exported_docs/ros2/Crystal_Clemmys_(crystal)\357\203\201.txt" "b/exported_docs/ros2/Crystal_Clemmys_(crystal)\357\203\201.txt" new file mode 100644 index 0000000..ce550a9 --- /dev/null +++ "b/exported_docs/ros2/Crystal_Clemmys_(crystal)\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: Crystal Clemmys (crystal) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Crystal-Clemmys.html +Section: Installation +-------------------------------------------------------------------------------- + +Crystal Clemmys (crystal)Table of ContentsSupported PlatformsNew features in this ROS 2 releaseChanges since the Bouncy releaseKnown IssuesCrystal Clemmysis the third release of ROS 2.Supported PlatformsCrystal Clemmys is primarily supported on the following platforms (seeREP 2000for full details):Tier 1 platforms:Ubuntu 18.04 (Bionic)Mac macOS 10.12 (Sierra)Windows 10Tier 2 platforms:Ubuntu 16.04 (Xenial)New features in this ROS 2 releaseActions in C / C++ (server/clientexamples)gazebo_ros_pkgsimage_transportnavigation2rosbag2rqtImprovement in memory managementIntrospection information about nodesLaunch system improvementsArgumentsNested launch filesConditionsPass params to NodesLaid the groundwork forfile-based logging and /rosout publishingTime and Duration API in PythonParameters work with Python nodesChanges since the Bouncy releaseChanges since theBouncy Bolsonrelease:geometry2 -tf2_ros::BufferAPI Changetf2_ros::Buffernow usesrclcpp::Time, with the constructor requiring ashared_ptrto arclcpp::Clockinstance. +Seehttps://github.com/ros2/geometry2/pull/67for details, with example usage:#include#include...# Assuming you have a rclcpp::Node my_nodetf2_ros::Bufferbuffer(my_node.get_clock());tf2_ros::TransformListenertf_listener(buffer);Allrclcppandrcutilslogging macros require semicolons.Seehttps://github.com/ros2/rcutils/issues/113for details.rcutils_get_error_string_safe()andrcl_get_error_string_safe()have been replaced withrcutils_get_error_string().strandrcl_get_error_string().str.Seehttps://github.com/ros2/rcutils/pull/121for details.rmw -rmw_initAPI ChangeThere are two new structs, thercl_context_tand thercl_init_options_t, which are used withrmw_init. +The init options struct is used to pass options down to the middleware and is an input tormw_init. +The context is a handle which is an output ofrmw_initfunction is used to identify which init-shutdown cycle each entity is associated with, where an “entity” is anything created like a node, guard condition, etc.This is listed here because maintainers of alternative rmw implementations will need to implement these new functions to have their rmw implementation work in Crystal.This is the function that had a signature change:rmw_initAdditionally, there are these new functions which need to be implemented by each rmw implementation:rmw_shutdownrmw_init_options_initrmw_init_options_copyrmw_init_options_finiHere’s an example of what minimally needs to be changed in an rmw implementation to adhere to this API change:rmw_fastrtps prrcl -rcl_initAPI ChangeLike thermwchange above, there’s two new structs inrclcalledrcl_context_tandrcl_init_options_t. +The init options are passed intorcl_initas an input and the context is passed in as an output. +The context is used to associate all other rcl entities to a specific init-shutdown cycle, effectively making init and shutdown no longer global functions, or rather those functions no longer use an global state and instead encapsulate all state within the context type.Any maintainers of a client library implementation (that also usesrclunder the hood) will need to make changes to work with Crystal.These functions were removed:rcl_get_global_argumentsrcl_get_instance_idrcl_okThese functions had signature changes:rcl_initrcl_shutdownrcl_guard_condition_initrcl_guard_condition_init_from_rmwrcl_node_initrcl_timer_initThese are the new functions and types:rcl_context_trcl_get_zero_initialized_contextrcl_context_finircl_context_get_init_optionsrcl_context_get_instance_idrcl_context_is_validrcl_init_options_trcl_get_zero_initialized_init_optionsrcl_init_options_initrcl_init_options_copyrcl_init_options_finircl_init_options_get_rmw_init_optionsrcl_node_is_valid_except_contextrcl_publisher_get_contextrcl_publisher_is_valid_except_contextThese new and changed functions will impact how you handle init and shutdown in your client library. +For examples, look at the followingrclcppandrclpyPR’s:rclcpprclpyHowever, you may just continue to offer a single, global init and shutdown in your client library, and just store a single global context object.Known IssuesA race condition in Fast-RTPS 1.7.0 may cause messages to drop under stress (Issue).Using the TRANSIENT_LOCAL QoS setting with rmw_fastrtps_cpp can crash applications with large messages (Issue).Cross-vendor communication between rmw_fastrtps_cpp and other implementations is not functioning on Windows (Issue).When using OpenSplice (version < 6.9.190227) on macOS and Windows you might experience naming conflicts when when referencing field types with names from other packages if the same name also exist in the current package (Issue). +By updating to a newer OpenSplice version as well as at least the third patch release of Crystal the problem should be resolved. +On Linux updating to the latest Debian packages will include the newest OpenSplice version. + +Code Examples: + +Language: unknown +#include#include...# Assuming you have a rclcpp::Node my_nodetf2_ros::Bufferbuffer(my_node.get_clock());tf2_ros::TransformListenertf_listener(buffer); diff --git "a/exported_docs/ros2/DDS_implementations\357\203\201.txt" "b/exported_docs/ros2/DDS_implementations\357\203\201.txt" new file mode 100644 index 0000000..ee856d9 --- /dev/null +++ "b/exported_docs/ros2/DDS_implementations\357\203\201.txt" @@ -0,0 +1,49 @@ +Title: DDS implementations +URL: https://docs.ros.org/en/jazzy/Installation/DDS-Implementations.html +Section: Installation +-------------------------------------------------------------------------------- + +DDS implementationsBy default, ROS 2 uses DDS as itsmiddleware. +It is compatible with multiple DDS or RTPS (the DDS wire protocol) vendors. +There is currently support for eProsima’s Fast DDS, RTI’s Connext DDS, Eclipse Cyclone DDS, and GurumNetworks GurumDDS. +Seehttps://ros.org/reps/rep-2000.htmlfor supported DDS vendors by distribution.The default DDS vendor is eProsima’s Fast DDS.Working with Eclipse Cyclone DDSexplains how to utilize Cyclone DDS.Working with eProsima Fast DDSexplains how to utilize Fast DDS.Working with GurumNetworks GurumDDSexplains how to utilize GurumDDS.If you would like to use one of the other vendors you will need to install their software separately before building. +The ROS 2 build will automatically build support for vendors that have been installed and sourced correctly.Once you’ve installed a new DDS vendor, you can change the vendor used at runtime:Working with Multiple RMW Implementations.Detailed instructions for installing other DDS vendors are provided below.Platforms / Installation typesUbuntu Linux source installUbuntu Linux binary installOSX source installOSX binary installWindows source installWindows binary installUbuntu Linux source installRTI Connext (version 6.0.1, amd64 only)Deb packages provided in the ROS 2 apt repositoriesYou can install a deb package of RTI Connext available on the ROS 2 apt repositories. +You will need to accept a license from RTI.sudoaptupdate&&sudoaptinstall-q-yrti-connext-dds-6.0.1Source the setup file to set theNDDSHOMEenvironment variable.cd/opt/rti.com/rti_connext_dds-6.0.1/resource/scripts&&source./rtisetenv_x64Linux4gcc7.3.0.bash;cd-Note: when usingzshyou need to be in the directory of the script when sourcing it to have it work properlyNow you can build as normal and support for RTI will be built as well.Official binary packages from RTIYou can install the Connext 6.0.1 package for Linux provided by RTI, via options available foruniversity, purchase or evaluationAfter downloading, usechmod+xon the.runexecutable and then execute it. +Note that if you’re installing to a system directory usesudoas well.The default location is~/rti_connext_dds-6.0.1After installation, run RTI launcher and point it to your license file (obtained from RTI).Add the following line to your.bashrcfile pointing to your copy of the license.exportRTI_LICENSE_FILE=path/to/rti_license.datSource the setup file to set theNDDSHOMEenvironment variable.cd~/rti_connext_dds-6.0.1/resource/scripts&&source./rtisetenv_x64Linux4gcc7.3.0.bash;cd-Now you can build as normal and support for RTI will be built as well.Ubuntu Linux binary installRTI Connext (version 6.0.1, amd64 only)To use RTI Connext DDS there are full-suite install options available foruniversity, purchase or evaluationor you can install a libraries-only deb package of RTI Connext 6.0.1, available from the OSRF Apt repository +under anon-commercial license.To install the libs-only deb package:sudoaptupdate&&sudoaptinstall-q-yrti-connext-dds-6.0.1You will need to accept a license agreement from RTI, and will find an ‘rti_license.dat file in the installation.Add the following line to your.bashrcfile pointing to your copy of the license (and source it).exportRTI_LICENSE_FILE=path/to/rti_license.datAll options need you to source the setup file to set theNDDSHOMEenvironment variable:cd/opt/rti.com/rti_connext_dds-6.0.1/resource/scripts&&source./rtisetenv_x64Linux4gcc7.3.0.bash;cd-Note: the above may need modification to match your RTI installation locationIf you want to install the Connext DDS-Security plugins please refer tothis page.OSX source installRTI Connext (6.0.1)If you would like to also build against RTI Connext DDS there are options available foruniversity, purchase or evaluationYou also need a Java runtime installed to run the RTI code generator, which you can gethere.After installing, run RTI launcher and point it to your license file.Source the setup file to set theNDDSHOMEenvironment variable before building your workspace.source/Applications/rti_connext_dds-6.0.1/resource/scripts/rtisetenv_x64Darwin17clang9.0.bashYou may need to increase shared memory resources followinghttps://community.rti.com/kb/osx510If you want to install the Connext DDS-Security plugins please refer tothis page.OSX binary installEnable Connext supportTo use RTI Connext DDS there are options available foruniversity, purchase or evaluationAfter installing, run RTI launcher and point it to your license file.Source the setup file to set theNDDSHOMEenvironment variable before building your workspace.source/Applications/rti_connext_dds-6.0.1/resource/scripts/rtisetenv_x64Darwin17clang9.0.bashYou may need to increase shared memory resources followinghttps://community.rti.com/kb/osx510.If you want to install the Connext DDS-Security plugins please refer tothis page.Windows source installRTI Connext 6.0.1If you would like to also build against RTI Connext DDS there are options available foruniversity, purchase or evaluationAfter installing, use the RTI Launcher to load your license file.Then before building ROS 2, set up the Connext environment:call"C:\Program Files\rti_connext_dds-6.0.1\resource\scripts\rtisetenv_x64Win64VS2017.bat"Note that this path might need to be slightly altered depending on where you selected to install RTI Connext DDS, and which version of Visual Studio was selected. +The path above is the current default path as of version 6.0.1, but will change as the version numbers increment in the future.If you want to install the Connext DDS-Security plugins please refer tothis page.Windows binary installRTI ConnextTo use RTI Connext DDS there are options available foruniversity, purchase or evaluationAfter installing, run RTI launcher and point it to your license file.Then before using ROS 2, set up the Connext environment:call"C:\Program Files\rti_connext_dds-6.0.1\resource\scripts\rtisetenv_x64Win64VS2017.bat"If you want to install the Connext DDS-Security plugins please refer tothis page. + +Code Examples: + +Language: unknown +sudoaptupdate&&sudoaptinstall-q-yrti-connext-dds-6.0.1 + +Language: unknown +cd/opt/rti.com/rti_connext_dds-6.0.1/resource/scripts&&source./rtisetenv_x64Linux4gcc7.3.0.bash;cd- + +Language: unknown +exportRTI_LICENSE_FILE=path/to/rti_license.dat + +Language: unknown +cd~/rti_connext_dds-6.0.1/resource/scripts&&source./rtisetenv_x64Linux4gcc7.3.0.bash;cd- + +Language: unknown +sudoaptupdate&&sudoaptinstall-q-yrti-connext-dds-6.0.1 + +Language: unknown +exportRTI_LICENSE_FILE=path/to/rti_license.dat + +Language: unknown +cd/opt/rti.com/rti_connext_dds-6.0.1/resource/scripts&&source./rtisetenv_x64Linux4gcc7.3.0.bash;cd- + +Language: unknown +source/Applications/rti_connext_dds-6.0.1/resource/scripts/rtisetenv_x64Darwin17clang9.0.bash + +Language: unknown +source/Applications/rti_connext_dds-6.0.1/resource/scripts/rtisetenv_x64Darwin17clang9.0.bash + +Language: unknown +call"C:\Program Files\rti_connext_dds-6.0.1\resource\scripts\rtisetenv_x64Win64VS2017.bat" + +Language: unknown +call"C:\Program Files\rti_connext_dds-6.0.1\resource\scripts\rtisetenv_x64Win64VS2017.bat" diff --git "a/exported_docs/ros2/Dashing_Diademata_(dashing)\357\203\201.txt" "b/exported_docs/ros2/Dashing_Diademata_(dashing)\357\203\201.txt" new file mode 100644 index 0000000..a4dda86 --- /dev/null +++ "b/exported_docs/ros2/Dashing_Diademata_(dashing)\357\203\201.txt" @@ -0,0 +1,155 @@ +Title: Dashing Diademata (dashing) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Dashing-Diademata.html +Section: Installation +-------------------------------------------------------------------------------- + +Dashing Diademata (dashing)Table of ContentsSupported PlatformsInstallationNew features in this ROS 2 releaseChanges since the Crystal releaseDeclaring Parametersament_cmakerclcpprclcpp_componentsrclpyrosidlrosidl_generator_cpprosidl_generator_pylaunchrmwactionsrvizKnown IssuesTimeline before the releaseDashing Diadematais the fourth release of ROS 2.Supported PlatformsDashing Diademata is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 18.04 (Bionic):amd64andarm64Mac macOS 10.12 (Sierra)Windows 10 (Visual Studio 2019)Tier 2 platforms:Ubuntu 18.04 (Bionic):arm32Tier 3 platforms:Debian Stretch (9):amd64,arm64andarm32OpenEmbedded Thud (2.6) / webOS OSE:arm32andx86For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Dashing DiademataNew features in this ROS 2 releaseA few features and improvements we would like to highlight:Componentsare now the recommended way to write your node. +They can be used standalone as well as being composed within a process and both ways are fully support fromlaunchfiles.Theintra-process communication(C++ only) has been improved - both in terms of latency as well as minimizing copies.The Python client library has been updated to match most of the C++ equivalent and some important bug fixes and improvements have landed related to memory usage and performance.Parameters are now a complete alternative todynamic_reconfigurefrom ROS 1 including constraints like ranges or being read-only.By relying on (a subset of)IDL 4.2for the message generation pipeline it is now possible to use.idlfiles (beside.msg/.srv/.actionfiles). +This change comes with support for optional UTF-8 encoding for ordinary strings as well as UTF-16 encoded multi-byte strings (seewide strings design article).Command line tools related toactionsandcomponents.Support for Deadline, Lifespan & Liveliness quality of service settings.MoveIt 2alpha release.Please see theDashing meta ticketon GitHub, which contains more information as well as references to specific tickets with additional details.Changes since the Crystal releaseDeclaring ParametersThere have been some changes to the behavior of parameters starting in Dashing, which have also lead to some new API’s and the deprecation of other API’s. +See therclcppandrclpysections below for more information about API changes.Getting and Setting Undeclared ParametersAs of Dashing, parameters now need to be declared before being accessed or set.Before Dashing, you could callget_parameter(name)and get either a value, if it had been previously set, or a parameter of typePARAMETER_NOT_SET. +You could also callset_parameter(name,value)at any point, even if the parameter was previously unset.Since Dashing, you need to first declare a parameter before getting or setting it. +If you try to get or set an undeclared parameter you will either get an exception thrown, e.g. ParameterNotDeclaredException, or in certain cases you will get an unsuccessful result communicated in a variety of ways (see specific functions for more details).However, you can get the old behavior (mostly, see the note in the next paragraph) by using theallow_undeclared_parametersoption when creating your node. +You might want to do this in order to avoid code changes for now, or in order to fulfill some uncommon use cases. +For example, a “global parameter server” or “parameter blackboard” may want to allow external nodes to set new parameters on itself without first declaring them, so it may use theallow_undeclared_parametersoption to accomplish that. +In most cases, however, this option is not recommended because it makes the rest of the parameter API less safe to bugs like parameter name typos and “use before set” logical errors.Note that usingallow_undeclared_parameterswill get you most of the old behavior specifically for “get” and “set” methods, but it will not revert all the behavior changes related to parameters back to how it was for ROS Crystal. +For that you need to also set theautomatically_declare_parameters_from_overridesoption totrue, which is described below inParameter Configuration using a YAML File.Declaring a Parameter with a ParameterDescriptorAnother benefit to declaring your parameters before using them, is that it allows you to declare a parameter descriptor at the same time.Now when declaring a parameter you may include a customParameterDescriptoras well as a name and default value. +TheParameterDescriptoris defined as a message inrcl_interfaces/msg/ParameterDescriptorand contains meta data likedescriptionand constraints likeread_onlyorinteger_range. +These constraints can be used to reject invalid values when setting parameters and/or as hints to external tools about what values are valid for a given parameter. +Theread_onlyconstraint will prevent the parameter’s value from changing after being declared, as well as prevent if from being undeclared.For reference, here’s a link to theParameterDescriptormessage as of the time of writing this:https://github.com/ros2/rcl_interfaces/blob/0aba5a142878c2077d7a03977087e7d74d40ee68/rcl_interfaces/msg/ParameterDescriptor.msg#L1Parameter Configuration using a YAML FileAs of Dashing, parameters in a YAML configuration file, e.g. passed to the node via the command line argument__params:=, are only used to override a parameter’s default value when declaring the parameter.Before Dashing, any parameters you passed via a YAML file would be implicitly set on the node.Since Dashing, this is no longer the case, as parameters need to be declared in order to appear on the node to external observers, likeros2paramlist.The old behavior may be achieved using theautomatically_declare_parameters_from_overridesoption when creating a node. +This option, if set totrue, will automatically declare all parameters in the input YAML file when the node is constructed. +This may be used to avoid major changes to your existing code or to serve specific use cases. +For example, a “global parameter server” may want to be seeded with arbitrary parameters on launch, which it could not have declared ahead of time. +Most of the time, however, this option is not recommended, as it may lead to setting a parameter in a YAML file with the assumption that the node will use it, even if the node does not actually use it.In the future we hope to have a checker that will warn you if you pass a parameter to a node that it was not expecting.The parameters in the YAML file will continue to influence the value of parameters when they are first declared.ament_cmakeThe CMake functionament_index_has_resourcewas returning eitherTRUEorFALSE. +As ofthis releaseit returns either the prefix path in case the resource was found orFALSE.If you are using the return value in a CMake condition like this:ament_index_has_resource(var...)if(${var})you need to update the condition to ensure it considers a string value asTRUE:if(var)rclcppBehavior Change forNode::get_node_names()The functionNodeGraph::get_node_names(), and therefore alsoNode::get_node_names(), now returns astd::vectorcontaining fully qualified node names with their namespaces included, instead of just the node names.Changed the Way that Options are Passed to NodesExtended arguments (beyond name and namespace) to therclcpp::Node()constructor have been replaced with arclcpp::NodeOptionsstructure. +Seeros2/rclcpp#622for details about the structure and default values of the options.If you are using any of the extended arguments torclcpp::Node()like this:autocontext=rclcpp::contexts::default_context::get_global_default_context();std::vectorargs;std::vectorparams={rclcpp::Parameter("use_sim_time",true)};autonode=std::make_shared("foo_node","bar_namespace",context,args,params);You need to update to use theNodeOptionsstructurestd::vectorargs;std::vectorparams={rclcpp::Parameter("use_sim_time",true)};rclcpp::NodeOptionsnode_options;node_options.arguments(args);node_options.parameter_overrides(params);autonode=std::make_shared("foo_node","bar_namespace",node_options);Changes to Creating Publishers and SubscriptionsThere have been a few changes to creating publishers and subscriptions which are new in Dashing:QoS settings are now passed using the newrclcpp::QoSclass, and the API encourages the user to specify at least the history depth.Options are now passed as an object, i.e.rclcpp::PublisherOptionsandrclcpp::SubscriptionOptions.All changes are backwards compatible (no code changes are required), but several existing call styles have been deprecated. +Users are encouraged to update to the new signatures.In the past, when creating a publisher or subscription, you could either not specify any QoS settings (e.g. just provide topic name for a publisher) or you could specify a “qos profile” data structure (of typermw_qos_profile_t) with all the settings already set. +Now you must use the newrclcpp::QoSobject to specify your QoS and at least the history settings for your QoS. +This encourages the user to specify a history depth when usingKEEP_LAST, rather than defaulting it to a value that may or may not be appropriate.In ROS 1, this was known as thequeue_sizeand it was required in both C++ and Python. +We’re changing the ROS 2 API to bring this requirement back.Also, any options which could previously be passed during creation of a publisher or subscription have now been encapsulated in anrclcpp::PublisherOptionsandrclcpp::SubscriptionOptionsclass respectively. +This allows for shorter signatures, more convenient use, and for adding new future options without breaking API.Some signatures for creating publishers and subscribers are now deprecated, and new signatures have been added to allow you to use the newrclcpp::QoSand publisher/subscription option classes.These are the new and recommended API’s:template,typenamePublisherT=::rclcpp::Publisher>std::shared_ptrcreate_publisher(conststd::string&topic_name,constrclcpp::QoS&qos,constPublisherOptionsWithAllocator&options=PublisherOptionsWithAllocator());template,typenameSubscriptionT=rclcpp::Subscription::type,AllocatorT>>std::shared_ptrcreate_subscription(conststd::string&topic_name,constrclcpp::QoS&qos,CallbackT&&callback,constSubscriptionOptionsWithAllocator&options=SubscriptionOptionsWithAllocator(),typenamerclcpp::message_memory_strategy::MessageMemoryStrategy::type,AllocatorT>::SharedPtrmsg_mem_strat=nullptr);And these are the deprecated ones:template,typenamePublisherT=::rclcpp::Publisher>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptrcreate_publisher(conststd::string&topic_name,size_tqos_history_depth,std::shared_ptrallocator);template,typenamePublisherT=::rclcpp::Publisher>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptrcreate_publisher(conststd::string&topic_name,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,std::shared_ptrallocator=nullptr);template,typenameSubscriptionT=rclcpp::Subscription::type,Alloc>>[[deprecated("use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptrcreate_subscription(conststd::string&topic_name,CallbackT&&callback,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptrallocator=nullptr);template,typenameSubscriptionT=rclcpp::Subscription::type,Alloc>>[[deprecated("use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptrcreate_subscription(conststd::string&topic_name,CallbackT&&callback,size_tqos_history_depth,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptrallocator=nullptr);The change to how QoS is passed is most likely to impact users.A typical change for a publisher looks like this:- pub_ = create_publisher("chatter");+ pub_ = create_publisher("chatter", 10);And for a subscription:- sub_ = create_subscription("chatter", callback);+ sub_ = create_subscription("chatter", 10, callback);If you have no idea what depth to use and don’t care right now (maybe just prototyping), then we recommend using10, as that was the default before and should preserve existing behavior.More in depth documentation about how to select an appropriate depth is forthcoming.This is an example of a slightly more involved change to avoid the newly deprecated API’s:- // Creates a latched topic- rmw_qos_profile_t qos = rmw_qos_profile_default;- qos.depth = 1;- qos.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;-model_xml_.data = model_xml;node_handle->declare_parameter("robot_description", model_xml);description_pub_ = node_handle->create_publisher(- "robot_description", qos);+ "robot_description",+ // Transient local is similar to latching in ROS 1.+ rclcpp::QoS(1).transient_local());See the pull request (and connected pull requests) that introduced the QoS change for more examples and details:https://github.com/ros2/rclcpp/pull/713https://github.com/ros2/demos/pull/332https://github.com/ros2/robot_state_publisher/pull/19and others…Changes Due to Declare Parameter ChangeFor details about the actual behavior change, seeDeclaring Parametersabove.There are several new API calls in therclcpp::Node’s interface:Methods that declare parameters given a name, optional default value, optional descriptor, and return the value actually set:constrclcpp::ParameterValue&rclcpp::Node::declare_parameter(conststd::string&name,constrclcpp::ParameterValue&default_value=rclcpp::ParameterValue(),constrcl_interfaces::msg::ParameterDescriptor¶meter_descriptor=rcl_interfaces::msg::ParameterDescriptor());templateautorclcpp::Node::declare_parameter(conststd::string&name,constParameterT&default_value,constrcl_interfaces::msg::ParameterDescriptor¶meter_descriptor=rcl_interfaces::msg::ParameterDescriptor());templatestd::vectorrclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map¶meters);templatestd::vectorrclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map>¶meters);A method to undeclare parameters and to check if a parameter has been declared:voidrclcpp::Node::undeclare_parameter(conststd::string&name);boolrclcpp::Node::has_parameter(conststd::string&name)const;Some convenience methods that did not previously exist:rcl_interfaces::msg::SetParametersResultrclcpp::Node::set_parameter(constrclcpp::Parameter¶meter);std::vectorrclcpp::Node::get_parameters(conststd::vector&names)const;rcl_interfaces::msg::ParameterDescriptorrclcpp::Node::describe_parameter(conststd::string&name)const;A new method to set the callback which is called anytime a parameter will be changed, giving you the opportunity to reject it:usingOnParametersSetCallbackType=rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;OnParametersSetCallbackTyperclcpp::Node::set_on_parameters_set_callback(OnParametersSetCallbackTypecallback);There were also several deprecated methods:template[[deprecated("use declare_parameter() instead")]]voidrclcpp::Node::set_parameter_if_not_set(conststd::string&name,constParameterT&value);template[[deprecated("use declare_parameters() instead")]]voidrclcpp::Node::set_parameters_if_not_set(conststd::string&name,conststd::map&values);template[[deprecated("use declare_parameter() and it's return value instead")]]voidrclcpp::Node::get_parameter_or_set(conststd::string&name,ParameterT&value,constParameterT&alternative_value);template[[deprecated("use set_on_parameters_set_callback() instead")]]voidrclcpp::Node::register_param_change_callback(CallbackT&&callback);Memory StrategyThe interfacerclcpp::memory_strategy::MemoryStrategywas using the typedefWeakNodeVectorin various method signatures. +As of Dashing the typedef has been been changed toWeakNodeListand with it the type of the parameter in various methods. +Any custom memory strategy needs to be updated to match the modified interface.The relevant API change can be found inros2/rclcpp#741.rclcpp_componentsThe correct way to implement composition in Dashing is by utilizing therclcpp_componentspackage.The following changes must be made to nodes in order to correctly implement runtime composition:The Node must have a constructor that takesrclcpp::NodeOptions:classListener:publicrclcpp::Node{Listener(constrclcpp::NodeOptions&options):Node("listener",options){}};C++ registration macros (if present) need to be updated to use therclcpp_componentsequivalent. +If not present, registration macros must be added in one translation unit.// Insert at bottom of translation unit, e.g. listener.cpp#include"rclcpp_components/register_node_macro.hpp"// Use fully-qualifed name in registrationRCLCPP_COMPONENTS_REGISTER_NODE(composition::Listener);CMake registration macros (if present) need to be updated. +If not present, registration macros must be added to the project’s CMake.add_library(listenersrc/listener.cpp)rclcpp_components_register_nodes(listener"composition::Listener")For more information on composition, seethe tutorialrclpyChanges to Creating Publishers, Subscriptions, and QoS ProfilesPrior to Dashing, you could optionally provide aQoSProfileobject when creating a publisher or subscription. +In an effort to encourage users to specify a history depth for message queues, we nowrequirethat a depth value orQoSProfileobject is given when creating publishers or subscriptions.To create a publisher, previously you would have written:node.create_publisher(Empty,'chatter')# Or using a keyword argument for QoSProfilenode.create_publisher(Empty,'chatter',qos_profile=qos_profile_sensor_data)In Dashing, prefer the following API that provides a depth value orQoSProfileobject as a third positional argument:# Assume a history setting of KEEP_LAST with depth 10node.create_publisher(Empty,'chatter',10)# Or pass a QoSProfile object directlynode.create_publisher(Empty,'chatter',qos_profile_sensor_data)Likewise for subscriptions, previously you would have written:node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg))# Or using a keyword argument for QoSProfilenode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile=qos_profile_sensor_data)In Dashing:# Assume a history setting of KEEP_LAST with depth 10node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),10)# Or pass a QoSProfile object directlynode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile_sensor_data)To ease the transition, users who do not use the new API will see deprecation warnings.Furthermore, we also require that when constructingQoSProfileobjects that a history policy and/or depth is set. +If a history policy ofKEEP_LASTis provided, then a depth argument is also required. +For example, these calls are valid:QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_ALL)QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST,depth=10)QoSProfile(depth=10)# equivalent to the previous lineAnd these calls will cause a deprecation warning:QoSProfile()QoSProfile(reliability=QoSReliabilityPolicy.RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)# KEEP_LAST but no depthQoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST)See the issue and pull request related to introducing this change for more details:https://github.com/ros2/rclpy/issues/342https://github.com/ros2/rclpy/pull/344Changes Due to Declare Parameter ChangeFor details about the actual behavior change, seeDeclaring Parametersabove. The changes are analogous to the ones inrclcpp.These are the new API methods available inrclpy.node.Nodeinterface:To declare parameters given a name, an optional default value (supported byrcl_interfaces.msg.ParameterValue) and an optional descriptor, returning the value actually set:defdeclare_parameter(name:str,value:Any=None,descriptor:ParameterDescriptor=ParameterDescriptor())->Parameterdefdeclare_parameters(namespace:str,parameters:List[Union[Tuple[str],Tuple[str,Any],Tuple[str,Any,ParameterDescriptor],]])->List[Parameter]To undeclare previously declared parameters and to check if a parameter has been declared beforehand:defundeclare_parameter(name:str)->Nonedefhas_parameter(name:str)->boolTo get and set parameter descriptors:defdescribe_parameter(name:str)->ParameterDescriptordefdescribe_parameters(names:List[str])->List[ParameterDescriptor]defset_descriptor(name:str,descriptor:ParameterDescriptor,alternative_value:Optional[ParameterValue]=None)->ParameterValueA convenience method to get parameters that may not have been declared:defget_parameter_or(name:str,alternative_value:Optional[Parameter]=None)->ParameterOther changesrclpy.parameter.Parametercan now guess its type without explicitly setting it (as long as it’s one of the supported ones byrcl_interfaces.msg.ParameterValue). +For example, this code:p=Parameter('myparam',Parameter.Type.DOUBLE,2.41)Is equivalent to this code:p=Parameter('myparam',value=2.41)This change does not break existing API.rosidlUntil Crystal each message generator package registered itself using theament_cmakeextension pointrosidl_generate_interfacesand was passed a set of.msg/.srv/.actionfiles. +As of Dashing the message generation pipeline is based on.idlfiles instead.Any message generator package needs to change and register itself using the new extension pointrosidl_generate_idl_interfaceswhich passes only.idlfiles instead. +The message generators for the commonly supported languages C, C++, and Python as well as the typesupport packages for introspection, Fast RTPS, Connext and OpenSplice have already been updated (seeros2/rosidl#334). +The CMake code callingrosidl_generate_interfaces()can either pass.idlfiles directly or pass.msg/.srv/.actionwhich will then internally be converted into.idlfiles before being passed to each message generator.The format of.msg/.srv/.actionfiles is not being evolved in the future. +The mapping between.msg/.srv/.actionfiles and.idlfiles is described inthis design article. +Asecond design articledescribes the supported features in.idlfiles. +In order to leverage any of the new features existing interfaces need to be converted (e.g. using the command line toolsmsg2idl/srv2idl/action2idl).To distinguish same type names, but with different namespaces, the introspection structs now contain a namespace field that replaces the package name (seeros2/rosidl#335).Mapping of char in .msg filesInROS 1charhas been deprecated for a long time and is being mapped touint8. +In ROS 2 until Crystalcharwas mapped to a single character (charin C / C++,strwith length 1 in Python) in an effort to provide a more natural mapping. +As of Dashing the ROS 1 semantic has been restored andcharmaps touint8again.rosidl_generator_cppThe C++ data structures generated for messages, services and actions provide setter methods for each field. +Until Crystal each setter returned a pointer to the data structure itself to enable the named parameter idiom. +As of Dashing these settersreturn a referenceinstead since that seems to be the more common signature as well as it clarifies that the returned value can’t be anullptr.rosidl_generator_pyUntil Crystal an array (fixed size) or sequence (dynamic size, optionally with an upper boundary) field in a message was stored as alistin Python. +As of Dashing the Python type for arrays / sequences of numeric values has been changed:an array of numeric values is stored as anumpy.ndarray(thedtypeis chosen to match the type of the numeric value)a sequence of numeric values is stored as anarray.array(thetypenameis chosen to match the type of the numeric value)As before an array / sequence of non-numeric types is still represented as alistin Python.This change brings a number of benefits:The new data structures ensure that each item in the array / sequence complies with the value range restrictions of the numeric type.The numeric values can be stored more efficiently in memory which avoid the overhead of Python objects for each item.The memory layout of both data structures allows to read and write all items of the array / sequence in a single operation which makes the conversion from and to Python significantly faster / more efficient.launchThelaunch_testingpackage caught up with thelaunchpackage redesign done in Bouncy Bolson. +The legacy Python API, already moved into thelaunch.legacysubmodule, has thus been deprecated and removed.Seelaunchexamplesanddocumentationfor reference on how to use its new API.Seedemos testsfor reference on how to use the newlaunch_testingAPI.rmwChanges since theCrystal Clemmysrelease:New API inrmw, a fini function forrmw_context_t:rmw_context_finiModification ofrmw, now passesrmw_context_ttormw_create_wait_set:rmw_create_wait_setNew APIs inrmwfor preallocating space for published and subscribed messages:rmw_init_publisher_allocationrmw_fini_publisher_allocationrmw_init_subscription_allocationrmw_fini_subscription_allocationrmw_serialized_message_sizeModification ofrmw, now passesrmw_publisher_allocation_torrmw_subscription_allocation_ttormw_publishandrmw_take, respectively. +Note that this argument can beNULLornullptr, which keeps existing Crystal behavior.rmw_publishrmw_takeType names returned byrmw_get_*_names_and_types*functions should have a fully-qualified namespace. +For example, instead ofrcl_interfaces/Parameterandrcl_interfaces/GetParameters, the returned type names should bercl_interface/msg/Parameterandrcl_interfaces/srv/GetParameters.actionsChanges torclcpp_action::Clientsignatures:The signature ofrclcpp_action::Client::async_send_goalhas changed. +Now users can optionally provide callback functions for thegoal responseand theresultusing the newSendGoalOptionsstruct. +The goal response callback is called when an action server accepts or rejects the goal and the result callback is called when the result for the goal is received. +Optional callbacks were also added torclcpp_action::Client::async_cancel_goalandrclcpp_action::Client::async_get_result.Changes to goal transition names:The names of goal state transitions have been refactored to reflect the design documention. +This affectsrcl_action,rclcpp_action, andrclpy. +Here is a list of the event name changes (Old name -> New name):GOAL_EVENT_CANCEL -> GOAL_EVENT_CANCEL_GOALGOAL_EVENT_SET_SUCCEEDED -> GOAL_EVENT_SUCCEEDGOAL_EVENT_SET_ABORTED -> GOAL_EVENT_ABORTGOAL_EVENT_SET_CANCELED -> GOAL_EVENT_CANCELEDChanges toCancelGoal.srv:Areturn_codefield was added to the response message of theCancelGoalservice. +This is to better communicate a reason for a failed service call. +See thepull requestand connected issue for details.rvizPlugins should use fully qualified type names otherwise a warning will be logged. +Forexample, use the typesensor_msgs/msg/Imageinstead ofsensor_msgs/Image. +SeePR introducing this changefor more details.Known Issues[ros2/rclcpp#715]There is an inconsistency in the way that parameter YAML files are loaded between standalone ROS 2 nodes and composed ROS 2 nodes. +Currently available workarounds are noted in anissue comment[ros2/rclpy#360]rclpy nodes ignorectrl-cwhen using OpenSplice on Windows.[ros2/rosidl_typesupport_opensplice#30]There is a bug preventing nesting a message inside of a service or action definition with the same name when using OpenSplice.[ros2/rclcpp#781]Callingget_parameter/list_parameterfrom withinon_set_parameter_callbackcauses a deadlock on Dashing. This is fixed for Eloquent, but is an ABI break so has not been backported to Dashing.[ros2/rclcpp#912]Inter-process communication forces a message copy when intra-process communication takes place between anstd::unique_ptrpublisher and a singlestd::unique_ptrsubscription (publishedstd::unique_ptris internally being promoted to anstd::shared_ptr).[ros2/rosbag2#125]Topics with unreliable QOS are not recorded.[ros2/rclcpp#715]Composable nodes cannot receive parameters via remapping. Supplying parameters to composable nodes can be accomplished using the methods described in[this comment].[ros2/rclcpp#893]rclcpp::Contextis not destroyed because of a reference cycle withrclcpp::GraphListener. This causes a memory leak. A fix has not been backported because of the risk of breaking ABI.Timeline before the releaseA few milestones leading up to the release:Mon. Apr 8th (alpha)First releases of core packages available. +Testing can happen from now on (some features might not have landed yet).Thu. May 2ndAPI freeze for core packagesMon. May 6th (beta)Updated releases of core packages available. +Additional testing of the latest features.Thu. May 16thFeature freeze. +Only bug fix releases should be made after this point. +New packages can be released independently.Mon. May 20th (release candidate)Updated releases of core packages available.Wed. May 29thFreeze rosdistro. +No PRs for Dashing on therosdistrorepo will be merged (reopens after the release announcement). + +Code Examples: + +Language: unknown +ament_index_has_resource(var...)if(${var}) + +Language: unknown +if(var) + +Language: unknown +autocontext=rclcpp::contexts::default_context::get_global_default_context();std::vectorargs;std::vectorparams={rclcpp::Parameter("use_sim_time",true)};autonode=std::make_shared("foo_node","bar_namespace",context,args,params); + +Language: unknown +std::vectorargs;std::vectorparams={rclcpp::Parameter("use_sim_time",true)};rclcpp::NodeOptionsnode_options;node_options.arguments(args);node_options.parameter_overrides(params);autonode=std::make_shared("foo_node","bar_namespace",node_options); + +Language: unknown +template,typenamePublisherT=::rclcpp::Publisher>std::shared_ptrcreate_publisher(conststd::string&topic_name,constrclcpp::QoS&qos,constPublisherOptionsWithAllocator&options=PublisherOptionsWithAllocator());template,typenameSubscriptionT=rclcpp::Subscription::type,AllocatorT>>std::shared_ptrcreate_subscription(conststd::string&topic_name,constrclcpp::QoS&qos,CallbackT&&callback,constSubscriptionOptionsWithAllocator&options=SubscriptionOptionsWithAllocator(),typenamerclcpp::message_memory_strategy::MessageMemoryStrategy::type,AllocatorT>::SharedPtrmsg_mem_strat=nullptr); + +Language: unknown +template,typenamePublisherT=::rclcpp::Publisher>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptrcreate_publisher(conststd::string&topic_name,size_tqos_history_depth,std::shared_ptrallocator);template,typenamePublisherT=::rclcpp::Publisher>[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]std::shared_ptrcreate_publisher(conststd::string&topic_name,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,std::shared_ptrallocator=nullptr);template,typenameSubscriptionT=rclcpp::Subscription::type,Alloc>>[[deprecated("use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptrcreate_subscription(conststd::string&topic_name,CallbackT&&callback,constrmw_qos_profile_t&qos_profile=rmw_qos_profile_default,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptrallocator=nullptr);template,typenameSubscriptionT=rclcpp::Subscription::type,Alloc>>[[deprecated("use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead")]]std::shared_ptrcreate_subscription(conststd::string&topic_name,CallbackT&&callback,size_tqos_history_depth,rclcpp::callback_group::CallbackGroup::SharedPtrgroup=nullptr,boolignore_local_publications=false,typenamerclcpp::message_memory_strategy::MessageMemoryStrategy::type,Alloc>::SharedPtrmsg_mem_strat=nullptr,std::shared_ptrallocator=nullptr); + +Language: unknown +- pub_ = create_publisher("chatter");+ pub_ = create_publisher("chatter", 10); + +Language: unknown +- sub_ = create_subscription("chatter", callback);+ sub_ = create_subscription("chatter", 10, callback); + +Language: unknown +- // Creates a latched topic- rmw_qos_profile_t qos = rmw_qos_profile_default;- qos.depth = 1;- qos.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;-model_xml_.data = model_xml;node_handle->declare_parameter("robot_description", model_xml);description_pub_ = node_handle->create_publisher(- "robot_description", qos);+ "robot_description",+ // Transient local is similar to latching in ROS 1.+ rclcpp::QoS(1).transient_local()); + +Language: unknown +constrclcpp::ParameterValue&rclcpp::Node::declare_parameter(conststd::string&name,constrclcpp::ParameterValue&default_value=rclcpp::ParameterValue(),constrcl_interfaces::msg::ParameterDescriptor¶meter_descriptor=rcl_interfaces::msg::ParameterDescriptor());templateautorclcpp::Node::declare_parameter(conststd::string&name,constParameterT&default_value,constrcl_interfaces::msg::ParameterDescriptor¶meter_descriptor=rcl_interfaces::msg::ParameterDescriptor());templatestd::vectorrclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map¶meters);templatestd::vectorrclcpp::Node::declare_parameters(conststd::string&namespace_,conststd::map>¶meters); + +Language: unknown +voidrclcpp::Node::undeclare_parameter(conststd::string&name);boolrclcpp::Node::has_parameter(conststd::string&name)const; + +Language: unknown +rcl_interfaces::msg::SetParametersResultrclcpp::Node::set_parameter(constrclcpp::Parameter¶meter);std::vectorrclcpp::Node::get_parameters(conststd::vector&names)const;rcl_interfaces::msg::ParameterDescriptorrclcpp::Node::describe_parameter(conststd::string&name)const; + +Language: unknown +usingOnParametersSetCallbackType=rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;OnParametersSetCallbackTyperclcpp::Node::set_on_parameters_set_callback(OnParametersSetCallbackTypecallback); + +Language: unknown +template[[deprecated("use declare_parameter() instead")]]voidrclcpp::Node::set_parameter_if_not_set(conststd::string&name,constParameterT&value);template[[deprecated("use declare_parameters() instead")]]voidrclcpp::Node::set_parameters_if_not_set(conststd::string&name,conststd::map&values);template[[deprecated("use declare_parameter() and it's return value instead")]]voidrclcpp::Node::get_parameter_or_set(conststd::string&name,ParameterT&value,constParameterT&alternative_value);template[[deprecated("use set_on_parameters_set_callback() instead")]]voidrclcpp::Node::register_param_change_callback(CallbackT&&callback); + +Language: unknown +classListener:publicrclcpp::Node{Listener(constrclcpp::NodeOptions&options):Node("listener",options){}}; + +Language: unknown +// Insert at bottom of translation unit, e.g. listener.cpp#include"rclcpp_components/register_node_macro.hpp"// Use fully-qualifed name in registrationRCLCPP_COMPONENTS_REGISTER_NODE(composition::Listener); + +Language: unknown +add_library(listenersrc/listener.cpp)rclcpp_components_register_nodes(listener"composition::Listener") + +Language: unknown +node.create_publisher(Empty,'chatter')# Or using a keyword argument for QoSProfilenode.create_publisher(Empty,'chatter',qos_profile=qos_profile_sensor_data) + +Language: unknown +# Assume a history setting of KEEP_LAST with depth 10node.create_publisher(Empty,'chatter',10)# Or pass a QoSProfile object directlynode.create_publisher(Empty,'chatter',qos_profile_sensor_data) + +Language: unknown +node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg))# Or using a keyword argument for QoSProfilenode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile=qos_profile_sensor_data) + +Language: unknown +# Assume a history setting of KEEP_LAST with depth 10node.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),10)# Or pass a QoSProfile object directlynode.create_subscription(BasicTypes,'chatter',lambdamsg:print(msg),qos_profile_sensor_data) + +Language: unknown +QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_ALL)QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST,depth=10)QoSProfile(depth=10)# equivalent to the previous line + +Language: unknown +QoSProfile()QoSProfile(reliability=QoSReliabilityPolicy.RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)# KEEP_LAST but no depthQoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST) + +Language: unknown +defdeclare_parameter(name:str,value:Any=None,descriptor:ParameterDescriptor=ParameterDescriptor())->Parameterdefdeclare_parameters(namespace:str,parameters:List[Union[Tuple[str],Tuple[str,Any],Tuple[str,Any,ParameterDescriptor],]])->List[Parameter] + +Language: unknown +defundeclare_parameter(name:str)->Nonedefhas_parameter(name:str)->bool + +Language: unknown +defdescribe_parameter(name:str)->ParameterDescriptordefdescribe_parameters(names:List[str])->List[ParameterDescriptor]defset_descriptor(name:str,descriptor:ParameterDescriptor,alternative_value:Optional[ParameterValue]=None)->ParameterValue + +Language: unknown +defget_parameter_or(name:str,alternative_value:Optional[Parameter]=None)->Parameter + +Language: unknown +p=Parameter('myparam',Parameter.Type.DOUBLE,2.41) + +Language: unknown +p=Parameter('myparam',value=2.41) diff --git "a/exported_docs/ros2/Demos\357\203\201.txt" "b/exported_docs/ros2/Demos\357\203\201.txt" new file mode 100644 index 0000000..b4cb720 --- /dev/null +++ "b/exported_docs/ros2/Demos\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Demos +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos.html +Section: Installation +-------------------------------------------------------------------------------- + +DemosUsing quality-of-service settings for lossy networksManaging nodes with managed lifecyclesSetting up efficient intra-process communicationRecording and playing back data withrosbagusing the ROS 1 bridgeUnderstanding real-time programmingExperimenting with a dummy robotLoggingCreating a content filtering subscriptionConfigure service introspectionExternal resourcesBridging communication between ROS 1 and ROS 2Motion planning for a MoveIt 2 armUsing Turtlebot 3 (community-contributed)Getting startedSimulatingNavigating in simulationLearning SLAM in simulation \ No newline at end of file diff --git "a/exported_docs/ros2/Deploying_on_IBM_Cloud_Kubernetes_[community-contributed]\357\203\201.txt" "b/exported_docs/ros2/Deploying_on_IBM_Cloud_Kubernetes_[community-contributed]\357\203\201.txt" new file mode 100644 index 0000000..f24d728 --- /dev/null +++ "b/exported_docs/ros2/Deploying_on_IBM_Cloud_Kubernetes_[community-contributed]\357\203\201.txt" @@ -0,0 +1,296 @@ +Title: Deploying on IBM Cloud Kubernetes [community-contributed] +URL: https://docs.ros.org/en/jazzy/Tutorials/Miscellaneous/Deploying-ROS-2-on-IBM-Cloud.html +Section: Installation +-------------------------------------------------------------------------------- + +Deploying on IBM Cloud Kubernetes [community-contributed]Table of ContentsAboutROS 2 on IBM CloudStep 1: Setting up your systema) Docker files?b) ROS 2 ImageStep 2: Running the image on IBM CloudStep 3: Using Custom ROS 2 PackagesExtra: Deleting Docker ImagesStep 4: Kubernetesa) Creating the Clusterb) Deploying your Docker ImageFinally!Step 5: Using CLI for your Docker ImageFinal RemarksAboutThis article describes how to get ROS 2 running on IBM Cloud using Docker files. It first gives a brief overview of docker images and how they work locally and then explores IBM Cloud and how the user can deploy their containers on it. +Afterwards, a short description of how the user can use their own custom packages for ROS 2 from github on IBM Cloud is provided. +A walkthrough of how to create a cluster and utilize Kubernetes on IBM Cloud is provided and finally the Docker image is deployed on the cluster. +Originally publishedhereandhere.ROS 2 on IBM CloudIn this tutorial, we show how you can easily integrate and run ROS 2 on +IBM Cloud with your custom packages.ROS 2 is the new generation of ROS which gives more control over +multi-robot formations. With the advancements of cloud computing, cloud +robotics are becoming more important in today’s age. In this tutorial, +we will go through a short introduction on running ROS 2 on IBM Cloud. By +the end of the tutorial, you will be able to create your own packages in +ROS 2 and deploy them to the cloud using docker files.The following instructions assume you’re using Linux and have been +tested with Ubuntu 18.04 (Bionic Beaver).Step 1: Setting up your systemBefore we go into how the exact process works, lets first make sure all +the required software is properly installed. We’ll point you towards the +appropriate sources to set up your system and only highlight the details +that pertain to our use-case.a) Docker files?Docker files are a form of containers that can run separate from your +system, this way, you can set-up potentially hundreds of different +projects without affecting one another. You can even set-up different +versions of Linux on one machine, without the need for virtual machine. +Docker files have an advantage of saving space and only utilizing your +system resources when running. In addition, dockers are versatile and +transferable. They contain all the required pre-requisites to run +separately, meaning that you can easily use a docker file for a specific +system or service without any cubersome steps!Excited yet? Let’s start off by installing docker to your system by +following the followinglink. +From the tutorial, you should have done some sanity checks to make sure +docker is properly set-up. Just in case, however, let’s run the +following command once again that uses the hello-world docker image:$sudodockerrunhello-worldYou should obtain the following output:HellofromDocker! +Thismessageshowsthatyourinstallationappearstobeworkingcorrectly. + +Togeneratethismessage,Dockertookthefollowingsteps:1.TheDockerclientcontactedtheDockerdaemon.2.TheDockerdaemonpulledthe"hello-world"imagefromtheDockerHub.(amd64)3.TheDockerdaemoncreatedanewcontainerfromthatimagewhichrunstheexecutablethatproducestheoutputyouarecurrentlyreading.4.TheDockerdaemonstreamedthatoutputtotheDockerclient,whichsentittoyourterminal. + +Totrysomethingmoreambitious,youcanrunanUbuntucontainerwith:$dockerrun-itubuntubash + +Shareimages,automateworkflows,andmorewithafreeDockerID:https://hub.docker.com/ + +Formoreexamplesandideas,visit:https://docs.docker.com/get-started/b) ROS 2 ImageROSannouncedimage containers for several ROS distributions in January 2019. More +detailed instructions on the use of ROS 2 docker images can be foundhere.Let’s skip through that and get to real-deal right away; creating a +local ROS 2 docker. We’ll create our own Dockerfile (instead of using a +ready Image) since we’ll need this method for deployment on IBM Cloud. +First, we create a new directory which will hold our Dockerfile and any +other files we need later on and navigate to it. Using your favorite +$EDITOR of choice, open a new file namedDockerfile(make sure the +file naming is correct):$mkdir~/ros2_docker + +$cd~/ros2_docker + +$$EDITORDockerfileInsert the following in theDockerfile, and save it (also foundhere):FROMros:foxy# install ros packageRUNapt-getupdate&&apt-getinstall-y\ros-${ROS_DISTRO}-demo-nodes-cpp\ros-${ROS_DISTRO}-demo-nodes-py&&\rm-rf/var/lib/apt/lists/*&&mkdir/ros2_home + +WORKDIR/ros2_home# launch ros packageCMD["ros2","launch","demo_nodes_cpp","talker_listener_launch.py"]FROM: creates a layer from the ros:foxy Docker imageRUN: builds your container by installing vim into it and creating +a directory called /ros2_homeWORKDIR: informs the container where the working directory should +be for itOf course, you are free to change the ROS distribution (foxyis used +here) or change the directory name. The above docker file sets up +ROS-foxy and installs the demo nodes for C++ and Python. Then it +launches a file which runs a talker and a listener node. We will see it +in action in just a few, but they act very similar to the +publisher-subscriber example found in theROS +wikiNow, we are ready to build the docker image to run ROS 2 in it (yes, it +is THAT easy!).Note: if you have errors due to insufficient privileges orpermission denied, try running the command withsudoprivileges:$dockerbuild.# You will see a bunch of lines that execute the docker file instructions followed by:Successfullybuilt0dc6ce7cb4870dc6ce7cb487will most probably be different for you, so keep note of +it and copy it somewhere for reference. You can always go back and check +the docker images you have on your system using:$sudodockerps-asNow, run the docker file using:$dockerrun-it0dc6ce7cb487[INFO][launch]:Alllogfilescanbefoundbelow/root/.ros/log/2020-10-28-02-41-45-177546-0b5d9ed123be-1[INFO][launch]:DefaultloggingverbosityissettoINFO[INFO][talker-1]:processstartedwithpid[28][INFO][listener-2]:processstartedwithpid[30][talker-1][INFO][1603852907.249886590][talker]:Publishing:'Hello World: 1'[listener-2][INFO][1603852907.250964490][listener]:Iheard:[HelloWorld:1][talker-1][INFO][1603852908.249786312][talker]:Publishing:'Hello World: 2'[listener-2][INFO][1603852908.250453386][listener]:Iheard:[HelloWorld:2][talker-1][INFO][1603852909.249882257][talker]:Publishing:'Hello World: 3'[listener-2][INFO][1603852909.250536089][listener]:Iheard:[HelloWorld:3][talker-1][INFO][1603852910.249845718][talker]:Publishing:'Hello World: 4'[listener-2][INFO][1603852910.250509355][listener]:Iheard:[HelloWorld:4][talker-1][INFO][1603852911.249506058][talker]:Publishing:'Hello World: 5'[listener-2][INFO][1603852911.250152324][listener]:Iheard:[HelloWorld:5][talker-1][INFO][1603852912.249556670][talker]:Publishing:'Hello World: 6'[listener-2][INFO][1603852912.250212678][listener]:Iheard:[HelloWorld:6]If it works correctly, you should see something similar to what is shown +above. As can be seen, there are two ROS nodes (a publisher and a +subscriber) running and their output is provided to us through ROS INFO.Step 2: Running the image on IBM CloudThe following steps assume you have an IBM cloud account and have +ibmcloud CLI installed. If not, please check thislinkout to get that done first.We also need to make sure that the CLI plug-in for the IBM Cloud +Container Registry is installed by running the command$ibmcloudplugininstallcontainer-registryAfterwards, login to your ibmcloud account through the terminal:$ibmcloudlogin--ssoFrom here, let’s create a container registry name-space. Make sure you +use a unique name that is also descriptive as to what it is. Here, I +usedros2nasr.$ibmcloudcrnamespace-addros2nasrIBM cloud has a lot of shortcuts that would help us get our container +onto the cloud right away. The command below builds the container and +tags it with the nameros2foxyand the version of1. Make sure +you use the correct registry name you created and you are free to change +the container name as you wish. The.at the end indicates that theDockerfileis in the current directory (and it is important), if not, +change it to point to the directory containing the Dockerfile.$ibmcloudcrbuild--tagregistry.bluemix.net/ros2nasr/ros2foxy:1.You can now make sure that the container has been pushed to the registry +you created by running the following command$ibmcloudcrimage-list +Listingimages... + +REPOSITORYTAGDIGESTNAMESPACECREATEDSIZESECURITYSTATUS +us.icr.io/ros2nasr/ros2foxy1031be29301e6ros2nasr36secondsago120MBNoIssues + +OKNext, it is important to log-in to your registry to run the docker +image. Again, if you face apermission deniederror, perform the +command with sudo privileges. Afterwards, run your docker file as shown +below.$ibmcloudcrlogin +Logginginto'registry.ng.bluemix.net'... +Loggedinto'registry.ng.bluemix.net'. +Logginginto'us.icr.io'... +Loggedinto'us.icr.io'. + +OK + +$dockerrun-v-itregistry.ng.bluemix.net/ros2nasr/ros2foxy:1Whereros2nasris the name of the registry you created andros2foxy:1is the tag of the docker container and the version as +explained previously.You should now see your docker file running and providing similar output +to that you saw when you ran it locally on your machine.Step 3: Using Custom ROS 2 PackagesSo now we have the full pipeline working, from creating the Dockerfile, +all the way to deploying it and seeing it work on IBM Cloud. But, what +if we want to use a custom set of packages we (or someone else) created?Well that all has to do with how you set-up your Dockerfile. Lets use +the example provided by ROS 2here. +Create a new directory with a new Dockerfile (or overwrite the existing +one) and add the following in it (or download the filehere)ARGFROM_IMAGE=ros:foxy +ARGOVERLAY_WS=/opt/ros/overlay_ws# multi-stage for cachingFROM$FROM_IMAGEAScacher# clone overlay sourceARGOVERLAY_WS +WORKDIR$OVERLAY_WS/src +RUNecho"\repositories: \n\ros2/demos: \n\type: git \n\url: https://github.com/ros2/demos.git \n\version:${ROS_DISTRO}\n\">../overlay.repos +RUNvcsimport./<../overlay.repos# copy manifests for cachingWORKDIR/opt +RUNmkdir-p/tmp/opt&&\find./-name"package.xml"|\xargscp--parents-t/tmp/opt&&\find./-name"COLCON_IGNORE"|\xargscp--parents-t/tmp/opt||true# multi-stage for buildingFROM$FROM_IMAGEASbuilder# install overlay dependenciesARGOVERLAY_WS +WORKDIR$OVERLAY_WSCOPY--from=cacher/tmp/$OVERLAY_WS/src./src +RUN./opt/ros/$ROS_DISTRO/setup.sh&&\apt-getupdate&&rosdepinstall-y\--from-paths\src/ros2/demos/demo_nodes_cpp\src/ros2/demos/demo_nodes_py\--ignore-src\&&rm-rf/var/lib/apt/lists/*# build overlay sourceCOPY--from=cacher$OVERLAY_WS/src./src +ARGOVERLAY_MIXINS="release"RUN./opt/ros/$ROS_DISTRO/setup.sh&&\colconbuild\--packages-select\demo_nodes_cpp\demo_nodes_py\--mixin$OVERLAY_MIXINS# source entrypoint setupENVOVERLAY_WS$OVERLAY_WSRUNsed--in-place--expression\'$isource "$OVERLAY_WS/install/setup.bash"'\/ros_entrypoint.sh# run launch fileCMD["ros2","launch","demo_nodes_cpp","talker_listener_launch.py"]Going through the lines shown, we can see how we can add custom packages +from github in 4 steps:Create an overlay with custom packages cloned from Github:ARGOVERLAY_WS +WORKDIR$OVERLAY_WS/src +RUNecho"\repositories: \n\ros2/demos: \n\type: git \n\url: https://github.com/ros2/demos.git \n\version:${ROS_DISTRO}\n\">../overlay.repos +RUNvcsimport./<../overlay.reposInstall package dependencies using rosdep# install overlay dependenciesARGOVERLAY_WS +WORKDIR$OVERLAY_WSCOPY--from=cacher/tmp/$OVERLAY_WS/src./src +RUN./opt/ros/$ROS_DISTRO/setup.sh&&\apt-getupdate&&rosdepinstall-y\--from-paths\src/ros2/demos/demo_nodes_cpp\src/ros2/demos/demo_nodes_py\--ignore-src\&&rm-rf/var/lib/apt/lists/*Build the packagesyou need# build overlay sourceCOPY--from=cacher$OVERLAY_WS/src./src +ARGOVERLAY_MIXINS="release"RUN./opt/ros/$ROS_DISTRO/setup.sh&&\colconbuild\--packages-select\demo_nodes_cpp\demo_nodes_py\--mixin$OVERLAY_MIXINSRunning the launch file# run launch fileCMD["ros2","launch","demo_nodes_cpp","talker_listener_launch.py"]Likewise, we can change the packages used, install their dependencies, +and then run them.Back to IBM CloudWith this Dockerfile, we can follow the same steps we did before to +deploy it on IBM Cloud. Since we already have our registry created, and +we’re logged in to IBM Cloud, we directly build our new Dockerfile. +Notice how I kept the tag the same but changed the version, this way I +can update the docker image created previously. (You are free to create +a completely new one if you want)$ibmcloudcrbuild--tagregistry.bluemix.net/ros2nasr/ros2foxy:2.Then, make sure you are logged in to the registry and run the new docker +image:$ibmcloudcrlogin +Logginginto'registry.ng.bluemix.net'... +Loggedinto'registry.ng.bluemix.net'. +Logginginto'us.icr.io'... +Loggedinto'us.icr.io'. + +OK + +$dockerrun-v-itregistry.ng.bluemix.net/ros2nasr/ros2foxy:2You should see, again, the same output. However, this time we did it +through custom packages from github, which allows us to utilize our +personally created packages for ROS 2 on IBM Cloud.Extra: Deleting Docker ImagesAs you may find yourself in need of deleting a specific docker image(s) +from IBM Cloud, this is how you should go about it!List all the images you have and find all the ones that share theIMAGEname corresponding toregistry.ng.bluemix.net/ros2nasr/ros2foxy:2(in my case). Then +delete them using theirNAMES$dockerrmyour_docker_NAMESDelete the docker image from IBM Cloud using itsIMAGEname$dockerrmiregistry.ng.bluemix.net/ros2nasr/ros2foxy:2Step 4: Kubernetesa) Creating the ClusterCreate a cluster using the Console. The instructions are foundhere. +The settings used are detailed below. These are merely suggestions and +can be changed if you need to. However, make sure you understand the +implications of your choices:Plan:StandardOrchestration Service:Kubernetes v1.18.10Infrastructure:ClassicLocation:Resource group:DefaultGeography:North America(you are free to change this)Availability:Single zone(you are free to change this but make +sure you understand the impact of your choices by checking the IBM +Cloud documentation.)Worker Zone:Toronto 01(choose the location that is physically +closest to you)Worker Pool:Virtual - shared, Ubuntu 18Memory: 16 GBWorker nodes per zone:1Master service endpoint:Both private & public endpointsResource details (Totally flexible):Cluster name:mycluster-tor01-rosibmTags:version:1After you create your cluster, you will be redirected to a page which +details how you can set up the CLI tools and access your cluster. Please +follow these instructions (or check the instructionshere)and +wait for the progress bar to show that the worker nodes you created are +ready by indicatingNormalnext to the cluster name. You can also +reach this screen from the IBM Cloud Console inside the Kubernetes.b) Deploying your Docker ImageFinally!Create a deployment configuration yaml file namedros2-deployment.yamlusing your favorite $EDITOR and insert the +following in it:apiVersion:apps/v1 +kind:Deployment +metadata:name: +spec:replicas:selector:matchLabels:app:template:metadata:labels:app:spec:containers:-name:image:.icr.io//:You should replace the tags shown between“<” “>”as describedhere. +The file in my case would look something like this:apiVersion:apps/v1 +kind:Deployment +metadata:name:ros2-deployment +spec:replicas:1selector:matchLabels:app:ros2-ibmcloudtemplate:metadata:labels:app:ros2-ibmcloudspec:containers:-name:ros2-ibmcloudimage:us.icr.io/ros2nasr/ros2foxy:2Deploy the file using the following command$kubectlapply-fros2-deployment.yaml +deployment.apps/ros2-deploymentcreatedNow your docker image is fully deployed on your cluster!Step 5: Using CLI for your Docker ImageNavigate to your cluster through the IBM Cloud console Kubernetes.Click onKubernetes dashboardon the top right corner of the page.You should now be able to see a full list of all the different +parameters of your cluster as well as its CPU and Memory Usage.Navigate toPodsand click on your deployment.On the top right corner, click onExec into podNow you are inside your docker image! You can source your workspace (if +needed) and run ROS 2! For example:root@ros2-deployment-xxxxxxxx:/opt/ros/overlay_ws#.install/setup.sh +root@ros2-deployment-xxxxxxxx:/opt/ros/overlay_ws#ros2launchdemo_nodes_cpptalker_listener_launch.pyFinal RemarksAt this point, you are capable of creating your own docker image using ROS 2 packages on github. It is also possible, with little changes to utilize local ROS 2 packages as well. This could be the topic of another article. However, you are encouraged to check out the followingDockerfilewhich uses a local copy of the demos repository. Similarly, you can use your own local package. + +Code Examples: + +Language: unknown +$sudodockerrunhello-world + +Language: unknown +HellofromDocker! +Thismessageshowsthatyourinstallationappearstobeworkingcorrectly. + +Togeneratethismessage,Dockertookthefollowingsteps:1.TheDockerclientcontactedtheDockerdaemon.2.TheDockerdaemonpulledthe"hello-world"imagefromtheDockerHub.(amd64)3.TheDockerdaemoncreatedanewcontainerfromthatimagewhichrunstheexecutablethatproducestheoutputyouarecurrentlyreading.4.TheDockerdaemonstreamedthatoutputtotheDockerclient,whichsentittoyourterminal. + +Totrysomethingmoreambitious,youcanrunanUbuntucontainerwith:$dockerrun-itubuntubash + +Shareimages,automateworkflows,andmorewithafreeDockerID:https://hub.docker.com/ + +Formoreexamplesandideas,visit:https://docs.docker.com/get-started/ + +Language: unknown +$mkdir~/ros2_docker + +$cd~/ros2_docker + +$$EDITORDockerfile + +Language: unknown +FROMros:foxy# install ros packageRUNapt-getupdate&&apt-getinstall-y\ros-${ROS_DISTRO}-demo-nodes-cpp\ros-${ROS_DISTRO}-demo-nodes-py&&\rm-rf/var/lib/apt/lists/*&&mkdir/ros2_home + +WORKDIR/ros2_home# launch ros packageCMD["ros2","launch","demo_nodes_cpp","talker_listener_launch.py"] + +Language: unknown +$dockerbuild.# You will see a bunch of lines that execute the docker file instructions followed by:Successfullybuilt0dc6ce7cb487 + +Language: unknown +$sudodockerps-as + +Language: unknown +$dockerrun-it0dc6ce7cb487[INFO][launch]:Alllogfilescanbefoundbelow/root/.ros/log/2020-10-28-02-41-45-177546-0b5d9ed123be-1[INFO][launch]:DefaultloggingverbosityissettoINFO[INFO][talker-1]:processstartedwithpid[28][INFO][listener-2]:processstartedwithpid[30][talker-1][INFO][1603852907.249886590][talker]:Publishing:'Hello World: 1'[listener-2][INFO][1603852907.250964490][listener]:Iheard:[HelloWorld:1][talker-1][INFO][1603852908.249786312][talker]:Publishing:'Hello World: 2'[listener-2][INFO][1603852908.250453386][listener]:Iheard:[HelloWorld:2][talker-1][INFO][1603852909.249882257][talker]:Publishing:'Hello World: 3'[listener-2][INFO][1603852909.250536089][listener]:Iheard:[HelloWorld:3][talker-1][INFO][1603852910.249845718][talker]:Publishing:'Hello World: 4'[listener-2][INFO][1603852910.250509355][listener]:Iheard:[HelloWorld:4][talker-1][INFO][1603852911.249506058][talker]:Publishing:'Hello World: 5'[listener-2][INFO][1603852911.250152324][listener]:Iheard:[HelloWorld:5][talker-1][INFO][1603852912.249556670][talker]:Publishing:'Hello World: 6'[listener-2][INFO][1603852912.250212678][listener]:Iheard:[HelloWorld:6] + +Language: unknown +$ibmcloudplugininstallcontainer-registry + +Language: unknown +$ibmcloudlogin--sso + +Language: unknown +$ibmcloudcrnamespace-addros2nasr + +Language: unknown +$ibmcloudcrbuild--tagregistry.bluemix.net/ros2nasr/ros2foxy:1. + +Language: unknown +$ibmcloudcrimage-list +Listingimages... + +REPOSITORYTAGDIGESTNAMESPACECREATEDSIZESECURITYSTATUS +us.icr.io/ros2nasr/ros2foxy1031be29301e6ros2nasr36secondsago120MBNoIssues + +OK + +Language: unknown +$ibmcloudcrlogin +Logginginto'registry.ng.bluemix.net'... +Loggedinto'registry.ng.bluemix.net'. +Logginginto'us.icr.io'... +Loggedinto'us.icr.io'. + +OK + +$dockerrun-v-itregistry.ng.bluemix.net/ros2nasr/ros2foxy:1 + +Language: unknown +ARGFROM_IMAGE=ros:foxy +ARGOVERLAY_WS=/opt/ros/overlay_ws# multi-stage for cachingFROM$FROM_IMAGEAScacher# clone overlay sourceARGOVERLAY_WS +WORKDIR$OVERLAY_WS/src +RUNecho"\repositories: \n\ros2/demos: \n\type: git \n\url: https://github.com/ros2/demos.git \n\version:${ROS_DISTRO}\n\">../overlay.repos +RUNvcsimport./<../overlay.repos# copy manifests for cachingWORKDIR/opt +RUNmkdir-p/tmp/opt&&\find./-name"package.xml"|\xargscp--parents-t/tmp/opt&&\find./-name"COLCON_IGNORE"|\xargscp--parents-t/tmp/opt||true# multi-stage for buildingFROM$FROM_IMAGEASbuilder# install overlay dependenciesARGOVERLAY_WS +WORKDIR$OVERLAY_WSCOPY--from=cacher/tmp/$OVERLAY_WS/src./src +RUN./opt/ros/$ROS_DISTRO/setup.sh&&\apt-getupdate&&rosdepinstall-y\--from-paths\src/ros2/demos/demo_nodes_cpp\src/ros2/demos/demo_nodes_py\--ignore-src\&&rm-rf/var/lib/apt/lists/*# build overlay sourceCOPY--from=cacher$OVERLAY_WS/src./src +ARGOVERLAY_MIXINS="release"RUN./opt/ros/$ROS_DISTRO/setup.sh&&\colconbuild\--packages-select\demo_nodes_cpp\demo_nodes_py\--mixin$OVERLAY_MIXINS# source entrypoint setupENVOVERLAY_WS$OVERLAY_WSRUNsed--in-place--expression\'$isource "$OVERLAY_WS/install/setup.bash"'\/ros_entrypoint.sh# run launch fileCMD["ros2","launch","demo_nodes_cpp","talker_listener_launch.py"] + +Language: unknown +ARGOVERLAY_WS +WORKDIR$OVERLAY_WS/src +RUNecho"\repositories: \n\ros2/demos: \n\type: git \n\url: https://github.com/ros2/demos.git \n\version:${ROS_DISTRO}\n\">../overlay.repos +RUNvcsimport./<../overlay.repos + +Language: unknown +# install overlay dependenciesARGOVERLAY_WS +WORKDIR$OVERLAY_WSCOPY--from=cacher/tmp/$OVERLAY_WS/src./src +RUN./opt/ros/$ROS_DISTRO/setup.sh&&\apt-getupdate&&rosdepinstall-y\--from-paths\src/ros2/demos/demo_nodes_cpp\src/ros2/demos/demo_nodes_py\--ignore-src\&&rm-rf/var/lib/apt/lists/* + +Language: unknown +# build overlay sourceCOPY--from=cacher$OVERLAY_WS/src./src +ARGOVERLAY_MIXINS="release"RUN./opt/ros/$ROS_DISTRO/setup.sh&&\colconbuild\--packages-select\demo_nodes_cpp\demo_nodes_py\--mixin$OVERLAY_MIXINS + +Language: unknown +# run launch fileCMD["ros2","launch","demo_nodes_cpp","talker_listener_launch.py"] + +Language: unknown +$ibmcloudcrbuild--tagregistry.bluemix.net/ros2nasr/ros2foxy:2. + +Language: unknown +$ibmcloudcrlogin +Logginginto'registry.ng.bluemix.net'... +Loggedinto'registry.ng.bluemix.net'. +Logginginto'us.icr.io'... +Loggedinto'us.icr.io'. + +OK + +$dockerrun-v-itregistry.ng.bluemix.net/ros2nasr/ros2foxy:2 + +Language: unknown +$dockerrmyour_docker_NAMES + +Language: unknown +$dockerrmiregistry.ng.bluemix.net/ros2nasr/ros2foxy:2 + +Language: unknown +apiVersion:apps/v1 +kind:Deployment +metadata:name: +spec:replicas:selector:matchLabels:app:template:metadata:labels:app:spec:containers:-name:image:.icr.io//: + +Language: unknown +apiVersion:apps/v1 +kind:Deployment +metadata:name:ros2-deployment +spec:replicas:1selector:matchLabels:app:ros2-ibmcloudtemplate:metadata:labels:app:ros2-ibmcloudspec:containers:-name:ros2-ibmcloudimage:us.icr.io/ros2nasr/ros2foxy:2 + +Language: unknown +$kubectlapply-fros2-deployment.yaml +deployment.apps/ros2-deploymentcreated + +Language: unknown +root@ros2-deployment-xxxxxxxx:/opt/ros/overlay_ws#.install/setup.sh +root@ros2-deployment-xxxxxxxx:/opt/ros/overlay_ws#ros2launchdemo_nodes_cpptalker_listener_launch.py diff --git "a/exported_docs/ros2/Deployment_Guidelines\357\203\201.txt" "b/exported_docs/ros2/Deployment_Guidelines\357\203\201.txt" new file mode 100644 index 0000000..b237bd9 --- /dev/null +++ "b/exported_docs/ros2/Deployment_Guidelines\357\203\201.txt" @@ -0,0 +1,64 @@ +Title: Deployment Guidelines +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Security/Deployment-Guidelines.html +Section: Installation +-------------------------------------------------------------------------------- + +Deployment GuidelinesGoal:Understand the best practices when deploying security artifacts into production systems.Tutorial level:AdvancedTime:20 minutesContentsBackgroundPrerequisitesGeneral GuidelinesBuilding a deployment scenarioGenerating the Docker ImageUnderstanding the compose fileRunning the exampleExamining the containersBackgroundTypical deployment scenarios often involve shipping containerized applications, or packages, into remote systems. +Special attention should be payed when deploying security enabled applications, requiring users to reason about the sensitivity of packaged files.Complying with theDDS Security standard, +thesros2package provides a collection of utilities for managing security under ROS 2 environments in a highly modular and flexible fashion.Basic core guidelines on how to organize the different certificates, keys and directories remains a critical factor to avoid compromising the security of the system. +This includes protection-awareness and criteria for selecting the minimum set of necessary files to be deployed upon remote production systems for minimizing security exposure.PrerequisitesA docker installation with the compose plugin. +Please refer to the installation steps detailed inDocker installationandCompose Plugin.(Recommended) A basic understanding onROS 2 Security design.(Recommended) Previous security tutorials completion. In particular:Setting up securityUnderstanding the security keystoreSetting access controlsGeneral GuidelinesROS 2 leverages DDS Security extensions to ensure security on message exchanges within the same enclave. +The different signed files and certificates within an enclave are generated from the private keys and certificates of aCertificate Authority (CA)trusted entity. +In fact, two different CA’s can be selected for identity and permissions, per enclave. +Those CA artifacts are stored insideprivate/andpublic/sub-directories of aKeystorewith the following folder structure:keystore +├── enclaves +│ └── ... +│ └── ... +├── private +│ └── ... +└── public + └── ...A good practice for the creation and usage of a certain Certificate Authority on a typical deployment for a production system, is to:Create it within the organization system intended for internal use only.Generate/modify desired enclaves bearing in mind that:Not all the generated enclaves should be deployed to all target devices.A reasonable way to proceed would be having one enclave per application, allowing for a separation of concerns.Shippublic/alongside with correspondingenclaves/into the different remote production devices during setup.Keep and protectprivate/keys and/or certification requests in the organization.It is important to note that ifprivate/files are lost, it won’t be possible to change access permissions, add or modify security profiles anymore.In addition, further practices may be taken into consideration:Granting read-only permissions to theenclaves/directory contents.If a PKCS#11 compliant URI is given for generating enclave’s private keys, aHardware Security Module (HSM)could be used to store them.The following table depicts a summary of the previous statements relating the Keystore directory with the Recommended location:Directory / LocationOrganizationTarget DeviceMaterial Sensitivitypublic✓✓Lowprivate✓✕Highenclaves✓✓MediumBuilding a deployment scenarioTo illustrate a simple deployment scenario, a new docker image will be built on top of the one provided byros:. +Starting from the image, three containers will be created with the aim of:Initializing the keystore in a local host’s shared volume.Simulating two deployed remote devices that interact with each other in a secure way.In this example, the local host serves as the organization’s system. +Let us start by creating a workspace folder:mkdir~/security_gd_tutorialcd~/security_gd_tutorialGenerating the Docker ImageIn order to build a new docker image, a Dockerfile is required. +The one proposed for this tutorial can be retrieved with the following command:# Download the Dockerfilewgethttps://raw.githubusercontent.com/ros2/ros2_documentation/jazzy/source/Tutorials/Advanced/Security/resources/deployment_gd/DockerfileNow, build the docker image with the command:# Build the base imagedockerbuild-tros2_security/deployment_tutorial--build-argROS_DISTRO=jazzy.Understanding the compose fileA compose configration file takes an image to create containers as services. +In this tutorial, three services are defined within the configuration:keystore-creator: That, similarly to previous tutorials, it internally initializes a new keystore tree directory. +This will createenclaves/public/andprivate/, which are explained in more detail inROS 2 Security enclaves. +Thekeystoredirectory is configured to be a shared volume across containers.listenerandtalker: Act as the remote device actors in this tutorial. +RequiredSecurityenvironment variables are sourced as well as the necessary keystore files from the shared volume.The compose configuration yaml file can be downloaded with:# Download the compose filewgethttps://raw.githubusercontent.com/ros2/ros2_documentation/jazzy/source/Tutorials/Advanced/Security/resources/deployment_gd/compose.deployment.yamlRunning the exampleIn the same working directory~/security_gd_tutorial, run:# Start the exampledockercompose-fcompose.deployment.yamlupThis should result in the following output:tutorial-listener-1:Foundsecuritydirectory:/keystore/enclaves/talker_listener/listenertutorial-talker-1:Foundsecuritydirectory:/keystore/enclaves/talker_listener/talkertutorial-listener-1:Publishing:'HelloWorld:'tutorial-talker-1:Iheard:[HelloWorld:]Examining the containersWhile having the containers running that simulate the two remote devices for this tutorial, attach to each of them by opening two different terminals and enter:# Terminal 1dockerexec-ittutorial-listener-1bashcdkeystore +tree# Terminal 2dockerexec-ittutorial-talker-1bashcdkeystore +treeA similar output to the one depicted below should be obtained:# Terminal 1keystore├──enclaves│├──governance.p7s│├──governance.xml│└──talker_listener│└──listener│├──cert.pem│├──governance.p7s│├──identity_ca.cert.pem│├──key.pem│├──permissions_ca.cert.pem│├──permissions.p7s│└──permissions.xml└──public├──ca.cert.pem├──identity_ca.cert.pem└──permissions_ca.cert.pem# Terminal 2keystore├──enclaves│├──governance.p7s│├──governance.xml│└──talker_listener│└──talker│├──cert.pem│├──governance.p7s│├──identity_ca.cert.pem│├──key.pem│├──permissions_ca.cert.pem│├──permissions.p7s│└──permissions.xml└──public├──ca.cert.pem├──identity_ca.cert.pem└──permissions_ca.cert.pemNote that:private/folder is not moved but left in the local host (organization).Each one of the deployed devices contain its own minimum enclave required for its application.NoteFor the sake of simplicity, the same CA is used within this enclave for both identity and permissions. + +Code Examples: + +Language: unknown +keystore +├── enclaves +│ └── ... +│ └── ... +├── private +│ └── ... +└── public + └── ... + +Language: unknown +mkdir~/security_gd_tutorialcd~/security_gd_tutorial + +Language: unknown +# Download the Dockerfilewgethttps://raw.githubusercontent.com/ros2/ros2_documentation/jazzy/source/Tutorials/Advanced/Security/resources/deployment_gd/Dockerfile + +Language: unknown +# Build the base imagedockerbuild-tros2_security/deployment_tutorial--build-argROS_DISTRO=jazzy. + +Language: unknown +# Download the compose filewgethttps://raw.githubusercontent.com/ros2/ros2_documentation/jazzy/source/Tutorials/Advanced/Security/resources/deployment_gd/compose.deployment.yaml + +Language: unknown +# Start the exampledockercompose-fcompose.deployment.yamlup + +Language: unknown +# Terminal 1dockerexec-ittutorial-listener-1bashcdkeystore +tree# Terminal 2dockerexec-ittutorial-talker-1bashcdkeystore +tree + +Language: unknown +# Terminal 1keystore├──enclaves│├──governance.p7s│├──governance.xml│└──talker_listener│└──listener│├──cert.pem│├──governance.p7s│├──identity_ca.cert.pem│├──key.pem│├──permissions_ca.cert.pem│├──permissions.p7s│└──permissions.xml└──public├──ca.cert.pem├──identity_ca.cert.pem└──permissions_ca.cert.pem# Terminal 2keystore├──enclaves│├──governance.p7s│├──governance.xml│└──talker_listener│└──talker│├──cert.pem│├──governance.p7s│├──identity_ca.cert.pem│├──key.pem│├──permissions_ca.cert.pem│├──permissions.p7s│└──permissions.xml└──public├──ca.cert.pem├──identity_ca.cert.pem└──permissions_ca.cert.pem diff --git "a/exported_docs/ros2/Developing_a_ROS_2_package\357\203\201.txt" "b/exported_docs/ros2/Developing_a_ROS_2_package\357\203\201.txt" new file mode 100644 index 0000000..fdfd80b --- /dev/null +++ "b/exported_docs/ros2/Developing_a_ROS_2_package\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: Developing a ROS 2 package +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Developing-a-ROS-2-Package.html +Section: Installation +-------------------------------------------------------------------------------- + +Developing a ROS 2 packageTable of ContentsPrerequisitesCreating a packageC++ PackagesPython PackagesCombined C++ and Python PackagesThis tutorial will teach you how to create your first ROS 2 application. +It is intended for developers who want to learn how to create custom packages in ROS 2, not for people who want to use ROS 2 with its existing packages.PrerequisitesInstall ROSInstall colconSetup your workspace by sourcing your ROS 2 installation.Creating a packageAll ROS 2 packages begin by running the commandros2pkgcreate--licenseApache-2.0--dependencies[deps]in your workspace (usually~/ros2_ws/src).To create a package for a specific client library:C++Pythonros2pkgcreate--build-typeament_cmake--licenseApache-2.0--dependencies[deps]ros2pkgcreate--build-typeament_python--licenseApache-2.0--dependencies[deps]You can then update thepackage.xmlwith your package info such as dependencies, descriptions, and authorship.C++ PackagesYou will mostly use theadd_executable()CMake macro along withament_target_dependencies([dependencies])to create executable nodes and link dependencies.To install your launch files and nodes, you can use theinstall()macro placed towards the end of the file but before theament_package()macro.An example for launch files and nodes:# Install launch filesinstall(DIRECTORYlaunchDESTINATIONshare/${PROJECT_NAME})# Install nodesinstall(TARGETS[node-names]DESTINATIONlib/${PROJECT_NAME})Python PackagesROS 2 follows Python’s standard module distribution process that usessetuptools. +For Python packages, thesetup.pyfile complements a C++ package’sCMakeLists.txt. +More details on distribution can be found in theofficial documentation.In your ROS 2 package, you should have asetup.cfgfile which looks like:[develop]script_dir=$base/lib/[install]install_scripts=$base/lib/and asetup.pyfile that looks like:importosfromglobimportglobfromsetuptoolsimportfind_packages,setuppackage_name='my_package'setup(name=package_name,version='0.0.0',# Packages to exportpackages=find_packages(exclude=['test']),# Files we want to install, specifically launch filesdata_files=[# Install marker file in the package index('share/ament_index/resource_index/packages',['resource/'+package_name]),# Include our package.xml file(os.path.join('share',package_name),['package.xml']),# Include all launch files.(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.[pxy][yma]*'))),],# This is important as wellinstall_requires=['setuptools'],zip_safe=True,author='ROS 2 Developer',author_email='ros2@ros.com',maintainer='ROS 2 Developer',maintainer_email='ros2@ros.com',keywords=['foo','bar'],classifiers=['Intended Audience :: Developers','License :: TODO','Programming Language :: Python','Topic :: Software Development',],description='My awesome package.',license='TODO',# Like the CMakeLists add_executable macro, you can add your python# scripts here.entry_points={'console_scripts':['my_script = my_package.my_script:main'],},)Combined C++ and Python PackagesWhen writing a package with both C++ and Python code, thesetup.pyfile andsetup.cfgfile are not used. +Instead, useament_cmake_python. + +Code Examples: + +Language: unknown +ros2pkgcreate--licenseApache-2.0--dependencies[deps] + +Language: unknown +ros2pkgcreate--build-typeament_cmake--licenseApache-2.0--dependencies[deps] + +Language: unknown +ros2pkgcreate--build-typeament_python--licenseApache-2.0--dependencies[deps] + +Language: unknown +ament_target_dependencies([dependencies]) + +Language: unknown +# Install launch filesinstall(DIRECTORYlaunchDESTINATIONshare/${PROJECT_NAME})# Install nodesinstall(TARGETS[node-names]DESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +[develop]script_dir=$base/lib/[install]install_scripts=$base/lib/ + +Language: unknown +importosfromglobimportglobfromsetuptoolsimportfind_packages,setuppackage_name='my_package'setup(name=package_name,version='0.0.0',# Packages to exportpackages=find_packages(exclude=['test']),# Files we want to install, specifically launch filesdata_files=[# Install marker file in the package index('share/ament_index/resource_index/packages',['resource/'+package_name]),# Include our package.xml file(os.path.join('share',package_name),['package.xml']),# Include all launch files.(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.[pxy][yma]*'))),],# This is important as wellinstall_requires=['setuptools'],zip_safe=True,author='ROS 2 Developer',author_email='ros2@ros.com',maintainer='ROS 2 Developer',maintainer_email='ros2@ros.com',keywords=['foo','bar'],classifiers=['Intended Audience :: Developers','License :: TODO','Programming Language :: Python','Topic :: Software Development',],description='My awesome package.',license='TODO',# Like the CMakeLists add_executable macro, you can add your python# scripts here.entry_points={'console_scripts':['my_script = my_package.my_script:main'],},) diff --git "a/exported_docs/ros2/Development_Distribution\357\203\201.txt" "b/exported_docs/ros2/Development_Distribution\357\203\201.txt" new file mode 100644 index 0000000..5148bb0 --- /dev/null +++ "b/exported_docs/ros2/Development_Distribution\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Development Distribution +URL: https://docs.ros.org/en/jazzy/Releases/Development.html +Section: Installation +-------------------------------------------------------------------------------- + +Development DistributionBelow is the ROS 2 distribution that is currently in development.Kilted Kaiju (codename ‘kilted’; May, 2025) \ No newline at end of file diff --git "a/exported_docs/ros2/Development_process_for_a_release\357\203\201.txt" "b/exported_docs/ros2/Development_process_for_a_release\357\203\201.txt" new file mode 100644 index 0000000..95e58de --- /dev/null +++ "b/exported_docs/ros2/Development_process_for_a_release\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Development process for a release +URL: https://docs.ros.org/en/jazzy/Releases/Release-Process.html +Section: Installation +-------------------------------------------------------------------------------- + +Development process for a releaseEach ROS 2 distribution goes through a process of development more than a year long that begins prior to the release of the previous distribution. +Below is a high-level view of this development process. +There is no specific due date for the items in this process, but in general earlier items should be completed before later items can be completed.For the progress through this process for a specific release, see that release’s documentation page.ItemNotesFind the ROS BossThe “ROS Boss” is the person in charge of shepherding a distribution through the development, release, update, and EOL’ing stages of its life. They are chosen from the internal ROS 2 team at Open Robotics.Run process to choose the distribution nameThe ROS Boss curates the process of choosing the distribution’s name, using input from sources such as the community and potential naming conflicts.Create distribution’s documentation pageEvery distribution has a documentation page that lists its vital statistics, such as planned release date, EOL date, and significant changes since the previous release.Set release timelineThe final weeks leading up to release day (usually, World Turtle Day) are hectic and full of deadlines, such as when to freeze the default RMW implementation. These deadlines must be planned well in advance.Produce roadmapWhile every contributor to ROS has their own planned features for each distribution, we try to maintain an overall roadmap of the new features and significant changes we expect to see in the distribution. The ROS Boss and the leader of the ROS 2 development team at Open Robotics work together with the ROS 2 TSC and other interested parties to produce a roadmap that is achievable in the time available and meets the needs of the ROS community.Announce roadmapThe list of planned features and significant changes is made public, via a GitHub issue that will track the progress on developing each item in the roadmap. Of course, this does not mean that the roadmap is fixed at this point, as development plans can change and we always (and frequently do) welcome new contributions even if they are not on the planned roadmap.Set target platforms and major dependenciesThe target platforms, in terms of operating system, distribution and version, must be set far enough in advance for development work on the infrastructure (such as support in the build farm) to proceed. Similarly, the versions of each major dependency (which Python version, which compiler(s), which version of Eigen, etc.) must also be fixed. This is done via an update toREP-2000.Add platform support to the build farmThe build farm is a critical part of the infrastructure supporting a ROS 2 distribution. It provides continuous integration facilities that help us maintain quality, and it builds the binary packages the community relies on to avoid building ROS 2 and packages from source. If the target platforms differ from the previous ROS 2 distribution, then the necessary support must be added to the build farm.Commission logo and related artworkA well-loved part of every ROS 2 distribution (and ROS distribution!) is the logo. The logo is commissioned from a professional artist based on the chosen distribution name. Based on the logo, other artwork such as the turtlesim icon are also produced.Create mailing list for the distributionVital for making critical announcements, a mailing list must be set up to contact people interested in knowing something about the distribution, such as that their package is failing to build into a binary on the build farm.Create test casesAs the development process enters the final few months, testing begins in earnest. The integration test cases that will be used during the final stages of development must be produced and provided to the release team who will be responsible for executing them.Announce upcoming RMW freezeThe RMW freeze is the point at which the default RMW implementation for the new distribution is feature-frozen. This gives developers a stable target to test their packages with, which is particularly important for the client library developers, who need to know what features of the RMW layer will be available for use by client libraries.Upgrade dependency packagesPackages depended on by ROS but not ROS software and not available in the platform package manager (such as aptitude for Ubuntu), the so-called “vendor packages”, must be updated to the versions specified in REP-2000 (or an appropriate version, for those not listed in REP-2000). This is particularly important on Windows.Create a detailed release planPlanning for the final two months of the development process is performed. This produces a detailed test plan, timelines of when certain packages must be available, and so on. It enables the finding of dependencies between steps in the release process and finding people to perform each of those steps.Freeze RMWThe RMW implementation is now feature-frozen. In theory, it can now be exhaustively tested to ensure it is working correctly by release day.Announce upcoming overall freezeThe next freeze after freezing the RMW implementation is to freeze the distribution as a whole. This is the point at which the core ROS packages become feature-frozen, giving developers of non-core packages a stable target to test their packages against, and giving distribution testers something to test that won’t change right after they’ve tested it.Freeze distributionFrom this point on, no new features can be added to any of the core ROS packages. Only bug fixes for the (inevitable) bugs found during the intensive integration test phases of development can be incorporated into the codebase. This means that Rolling Ridley is effectively frozen, temperarily.Announce upcoming branchThe branching of the new ROS 2 distribution from Rolling Ridley is an important moment. It is worth preparing for.Announce upcoming betaWhen the distribution enters beta, it is ready for wider testing by the ROS community. This beta happens soon after the distribution is branched from Rolling Ridely.Branch from Rolling RidleyThe new ROS 2 distribution is created by making a new branch from Rolling Ridley. In effect, the new distribution is born at this point in time. Meanwhile, Rolling Ridley is free from the development process and can roll on into the future, once again receiving new features.Add distribution to CIThe continuous integration system is updated to allow building using the new distribution’s branches and core ROS packages. This means that package developers can run CI for their packages against the new distribution, rather than Rolling Ridley.Begin building interim testing tarballsThe elite team of testers who will put the new distribution through its paces need something to test without compiling ROS 2 from source constantly. The build farm is used to produce a set of tarballs containing the distribution at a point in time for the testers to test.Add distribution documentationDetailed documentation about the distribution, such as the significant changes since the previous distribution, is added to the ROS 2 documentation site.Announce betaThe beta release of the distribution is made and the ROS community as a whole is invited to contribute to testing it (for those who aren’t already doing so). At this point, the more testers the better, because the distribution needs to be put through as wide a range of scenarios as possible to find bugs before the release.Final release preparationsAs the new distribution enters is absolutely-completely-everything-frozen phase, the final preparations are made for the release. These include things like producing binary packages using the build farm so there will be something to release.ReleaseThe big day, which if all goes to plan coincides with World Turtle Day on May 23rd. The distribution’s binary packages are made available in the release repository, and an announcement is made. Parties are held and the ROS 2 development team takes a well-earned break. \ No newline at end of file diff --git "a/exported_docs/ros2/Distributions\357\203\201.txt" "b/exported_docs/ros2/Distributions\357\203\201.txt" new file mode 100644 index 0000000..89bd013 --- /dev/null +++ "b/exported_docs/ros2/Distributions\357\203\201.txt" @@ -0,0 +1,13 @@ +Title: Distributions +URL: https://docs.ros.org/en/jazzy/Releases.html#rolling-distribution +Section: Installation +-------------------------------------------------------------------------------- + +DistributionsWhat is a Distribution?A ROS distribution is a versioned set of ROS packages. +These are akin to Linux distributions (e.g. Ubuntu). +The purpose of the ROS distributions is to let developers work against a relatively stable codebase until they are ready to roll everything forward. +Therefore once a distribution is released, we try to limit changes to bug fixes and non-breaking improvements for the core packages (every thing under ros-desktop-full). +That generally applies to the whole community, but for “higher” level packages, the rules are less strict, and so it falls to the maintainers of a given package to avoid breaking changes.List of DistributionsBelow is a list of current and historic ROS 2 distributions. +Rows in the table marked in green are the currently supported distributions.DistroRelease dateLogoEOL dateJazzy JaliscoMay 23rd, 2024May 2029Iron IrwiniMay 23rd, 2023November 2024Humble HawksbillMay 23rd, 2022May 2027Galactic GeocheloneMay 23rd, 2021December 9th, 2022Foxy FitzroyJune 5th, 2020June 20th, 2023Eloquent ElusorNovember 22nd, 2019November 2020Dashing DiademataMay 31st, 2019May 2021Crystal ClemmysDecember 14th, 2018December 2019Bouncy BolsonJuly 2nd, 2018July 2019Ardent ApaloneDecember 8th, 2017December 2018beta3September 13th, 2017December 2017beta2July 5th, 2017September 2017beta1December 19th, 2016Jul 2017alpha1 - alpha8August 31th, 2015December 2016Future DistributionsFor details on upcoming features see theroadmap.There is a new ROS 2 distribution released yearly on May 23rd (World Turtle Day).DistroRelease dateLogoEOL dateKilted KaijuMay 2025TBDNov 2026Rolling DistributionROS 2 Rolling Ridleyis the rolling development distribution of ROS 2. +It is described inREP 2002and was first introduced in June 2020.The Rolling distribution of ROS 2 serves two purposes:it is a staging area for future stable distributions of ROS 2, andit is a collection of the most recent development releases.As the name implies, Rolling is continuously updated andcan have in-place updates that include breaking changes. +We recommend that most people use the most recent stable distribution instead (seeList of Distributions).Packages released into the Rolling distribution will be automatically released into future stable distributions of ROS 2.Releasing a ROS 2 packageinto the Rolling distribution follows the same procedures as all other ROS 2 distributions. \ No newline at end of file diff --git "a/exported_docs/ros2/Documenting_a_ROS_2_package\357\203\201.txt" "b/exported_docs/ros2/Documenting_a_ROS_2_package\357\203\201.txt" new file mode 100644 index 0000000..61608a0 --- /dev/null +++ "b/exported_docs/ros2/Documenting_a_ROS_2_package\357\203\201.txt" @@ -0,0 +1,98 @@ +Title: Documenting a ROS 2 package +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Documenting-a-ROS-2-Package.html +Section: Installation +-------------------------------------------------------------------------------- + +Documenting a ROS 2 packageTable of ContentsPrerequisitesPackage Documentation OverviewBuilding Package DocsConfigurationrosdoc2.yamlconf.py, rosdoc2_settingsDoxyfileCustomizing Sphinx DocumentationCreating a Sphinx ProjectCustomizingindex.rstAdding Python API-DocsAdding C++ API-DocsIncluding an existing README.mdCI, docs.ros.orgFurther ReadingThis guide introduces the standard way to create documentation for ROS 2 packages. +For packages with binary releases this also results in the docs being hosted atdocs.ros.org/en//p//. +For information on how to contribute to this documentation on docs.ros.org, seeContributing to ROS 2 Documentation.PrerequisitesInstall ROSInstall rosdoc2Package Documentation OverviewThe type of documentation discussed in this guide is referred to as “package docs” or “API docs”. +For ROS packages that have been released on ROS Index, their documentation will be built on the ROS buildfarm, included on docs.ros.org, and visible via theAPIDocsbutton on index.ros.org.The tool responsible for generating ROS 2 package docs isrosdoc2.rosdoc2is a convenient wrapper around the commonly usedSphinxdocumentation framework. +Sphinx allows freeform written documentation as well as API documentation for python code generated from comments in the code. +Thebreathe+exhalepackages allow integration with Doxygen, to include autogenerated C++ API documentation as well.rosdoc2creates a default configuration for packages with no documentation or configuration at all, and applies options for a uniform theme and integration with other packages.Building Package DocsTo generate the documentation for a package in HTML format withrosdoc2, run:rosdoc2 build --package-path The documentation is written todocs_output//index.htmland can be viewed in a browser.ConfigurationThere are three configuration locations for ROS package docs:rosdoc2.yamlfor general settings,conf.pyfor sphinx settings and theDoxyfilefor doxygen settings. +For all of those, a default is assumed or generated if not present, so none of them is strictly required. +However, it might be necessary to create and modify those once you want to use features such as custom textual documentation pages.rosdoc2.yamlThis is the main entrypoint for rosdoc2. +It specifies generic settings, and can be used to control the execution of specific builders (Doxygen and Sphinx) and decides which builders to run.rosdoc2provides a multitude of configuration options, which can be adjusted in a config filerosdoc2.yaml. +To generate a defaultrosdoc2.yamlwhich you can then further customize, run:rosdoc2 default_config --package-path And addrosdoc2.yamlto the export section in yourpackage.xml:rosdoc2.yamlHowever, for most packages, the default settings inrosdoc2will suffice, and no custom config is necessary. +More information aboutrosdoc2.yamlcan be found in therosdoc2 readme.conf.py, rosdoc2_settingsThe final output of the package docs is (almost) always built by Sphinx. +Each Sphinx project is configured by aconf.pyfile in thedocdirectory. +If no configuration is present, a default Sphinx project is created and used when building the documentation. +If however aconf.pySphinx config is found in thedocsubdirectory of the package, this is used instead. +A custom Sphinx project is required if you want to include a standalone reStructuredText documentation page. +A standalone documentation page can be used to list multiple tutorials and guides; if that’s something you want for your package you’ll need to create a custom Sphinx project.rosdoc2provides additional settings toconf.pyand overrides some. +Information about changes done to the Sphinx settings are logged to the console with a[rosdoc2]prefix.DoxyfileDoxygen is a tool for automatically generating C++ API docs from code comments. +While Doxygen can also generate HTML output directly, in the usual workflow for ROS packages, Doxygen produces machine readable output in XML format which is then consumed by Sphinx and integrated with the rest of the documentation. +Doxygen-only docs are possible by only enabling the Doxygen builder inrosdoc2.yaml, but this is uncommon.Customizing Sphinx DocumentationCreating a Sphinx ProjectIn order to add standalone documentation pages in addition to the automatically generated API docs, a custom Sphinx project is necessary. +This should be created in a subdirectory calleddocin the package directory. +A new Sphinx project can be created by runningsphinx-quickstartin thedocdirectory, answeringnoto “Separate source and build directories”. +The wizard requires entering the project name, author and version, but this can later be removed and will be provided to Sphinx byrosdoc2from your packagespackage.xml. +More information about creating a sphinx project can be found on theSphinx quickstart page,Customizingindex.rstThesphinx-quickstartwizard creates anindex.rstfile, which is the custom landing page for your package, similar to a GithubREADMEfile.Adding Python API-DocsBy defaultrosdoc2uses thesphinx-apidoc tooland theautodoc Sphinx extensionto automatically generate documentation for python code. +In order for autodoc to find the Python modules in your package, it must be added to the python search path inconf.py:sys.path.insert(0,os.path.abspath('.'))This is becauserosdoc2wraps the customconf.pywith more configuration from a script which will be placed in the package. +In this case the.path inos.path.abspathrefers to the package’s directory root, not the package’sdocdirectory due to the interaction between rosdoc2 andconf.py.By default, package API docs are already reachable through the “Module Index” link that is present on the landing page. +For the API docs to also appear in the table of contents, simply add a link to themodulespage to yourindex.rst:..toctree:::maxdepth:2:caption:Contents: + + Python Modules Adding C++ API-DocsIf you would like to add your automatically generated API docs back to your custom landing page, add the linegenerated/indexto your documentation page where you would like the API docs to appear:..toctree:::maxdepth:2 + + C++ API Docs This adds the elements “Class Hierarchy”, “File Hierarchy” and “Reference” to the table of contents in the sidebar. +To make those appear under one “C++ API Docs” heading for a less cluttered sidebar, a separate file such ascpp_api_docs.rstcan be added, which links to the generated docs:cpp_api_docs.rstC++ API Docs============These are the autogenerated docs for the internal implementation...toctree:::maxdepth:3:caption:Contents: + + generated/indexWhich then also needs to be added inindex.rstto appear in the sidebar:index.rst..toctree:::maxdepth:2:caption:Contents: + + cpp_api_docsIncluding an existing README.mdIf your git repository already has an existingREADME.md, it is possible to reuse this as the landing page for the documentation, without duplicating the contents. +To correctly include a Markdown file in Sphinx while preserving relative links and images, some additional effort is required.First, create a proxy-filereadme_include.mdnext toindex.rst. +This is a markdown file which just includes the original README.md, but preserves the relative image paths, which would otherwise break in the next step:readme_include.md```{include} ../README.md +:relative-images: +```Then, include the contents of this file fromindex.rstusingmystto include markdown from rst:index.rst..include::readme_include.md:parser:myst_parser.sphinx_This also requires addingmyst_parserto the extensions inconf.py:conf.pyextensions=["myst_parser"]CI, docs.ros.orgThe ROS build farm usesrosdoc2to build the package documentation hosted atdocs.ros.org/en//p//. +To enable this, the repository containing the documentation must be configured inrosdistro/jazzy/distribution.yaml. +This would usually be the package source repository::doc:type:giturl:https://github.com//.gitversion:mainrelease:[...]The buildfarm hosts the documentation for every distribution separately, and periodically rebuilds it from the latest commit on the specified branch. +It is not required to tag a new release to update the hosted documentation. +To view the status of your package’s documentation build, search fordoc__onhttps://build.ros2.org. +One job is created for every distribution for which the package is released. +On each job page, you can see when a build was last triggered, as well as the status and logs of each build.Further Readingrosdoc2readme:https://github.com/ros-infrastructure/rosdoc2/blob/main/README.mdROS 2 design document on package documentation:https://design.ros2.org/articles/per_package_documentation.htmlThe ROS 2 cookbook:https://github.com/mikeferguson/ros2_cookbook/blob/main/pages/rosdoc2.md + +Code Examples: + +Language: unknown +rosdoc2 build --package-path + +Language: unknown +rosdoc2 default_config --package-path + +Language: unknown +rosdoc2.yaml + +Language: unknown +sys.path.insert(0,os.path.abspath('.')) + +Language: unknown +..toctree:::maxdepth:2:caption:Contents: + + Python Modules + +Language: unknown +..toctree:::maxdepth:2 + + C++ API Docs + +Language: unknown +C++ API Docs============These are the autogenerated docs for the internal implementation...toctree:::maxdepth:3:caption:Contents: + + generated/index + +Language: unknown +..toctree:::maxdepth:2:caption:Contents: + + cpp_api_docs + +Language: unknown +```{include} ../README.md +:relative-images: +``` + +Language: unknown +..include::readme_include.md:parser:myst_parser.sphinx_ + +Language: unknown +extensions=["myst_parser"] + +Language: unknown +:doc:type:giturl:https://github.com//.gitversion:mainrelease:[...] diff --git "a/exported_docs/ros2/Eclipse_Cyclone_DDS\357\203\201.txt" "b/exported_docs/ros2/Eclipse_Cyclone_DDS\357\203\201.txt" new file mode 100644 index 0000000..00c84ac --- /dev/null +++ "b/exported_docs/ros2/Eclipse_Cyclone_DDS\357\203\201.txt" @@ -0,0 +1,37 @@ +Title: Eclipse Cyclone DDS +URL: https://docs.ros.org/en/jazzy/Installation/DDS-Implementations/Working-with-Eclipse-CycloneDDS.html +Section: Installation +-------------------------------------------------------------------------------- + +Eclipse Cyclone DDSEclipse Cyclone DDS is a very performant and robust open-source DDS implementation. +Cyclone DDS is developed completely in the open as an Eclipse IoT project. +See also:https://projects.eclipse.org/projects/iot.cycloneddsPrerequisitesHaverosdep installed.Install packagesThe easiest way is to install from ROS 2 apt repository.sudoaptinstallros-jazzy-rmw-cyclonedds-cppBuild from source codeBuilding from source code is also another way to install.First, clone Cyclone DDS and rmw_cyclonedds in the ROS 2 workspace source directory.cdros2_ws/src +gitclonehttps://github.com/ros2/rmw_cycloneddsros2/rmw_cyclonedds-bjazzy +gitclonehttps://github.com/eclipse-cyclonedds/cycloneddseclipse-cyclonedds/cycloneddsThen, install necessary packages for Cyclone DDS.cd.. +rosdepinstall--fromsrc-iFinally, run colcon build.colconbuild--symlink-installSwitch to rmw_cycloneddsSwitch from other rmw to rmw_cyclonedds by specifying the environment variable.exportRMW_IMPLEMENTATION=rmw_cyclonedds_cppSee also:Working with multiple RMW implementationsRun the talker and listenerNow runtalkerandlistenerto test Cyclone DDS.ros2rundemo_nodes_cpptalkerros2rundemo_nodes_cpplistener + +Code Examples: + +Language: unknown +sudoaptinstallros-jazzy-rmw-cyclonedds-cpp + +Language: unknown +cdros2_ws/src +gitclonehttps://github.com/ros2/rmw_cycloneddsros2/rmw_cyclonedds-bjazzy +gitclonehttps://github.com/eclipse-cyclonedds/cycloneddseclipse-cyclonedds/cyclonedds + +Language: unknown +cd.. +rosdepinstall--fromsrc-i + +Language: unknown +colconbuild--symlink-install + +Language: unknown +exportRMW_IMPLEMENTATION=rmw_cyclonedds_cpp + +Language: unknown +ros2rundemo_nodes_cpptalker + +Language: unknown +ros2rundemo_nodes_cpplistener diff --git "a/exported_docs/ros2/Eloquent_Elusor_(eloquent)\357\203\201.txt" "b/exported_docs/ros2/Eloquent_Elusor_(eloquent)\357\203\201.txt" new file mode 100644 index 0000000..24756ff --- /dev/null +++ "b/exported_docs/ros2/Eloquent_Elusor_(eloquent)\357\203\201.txt" @@ -0,0 +1,46 @@ +Title: Eloquent Elusor (eloquent) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Eloquent-Elusor.html +Section: Installation +-------------------------------------------------------------------------------- + +Eloquent Elusor (eloquent)Table of ContentsSupported PlatformsInstallationNew features in this ROS 2 releaseChanges since the Dashing releasegeometry_msgsrclcpprmwros2clirvizTF2 BufferrclKnown IssuesTimeline before the releaseEloquent Elusoris the fifth release of ROS 2.Supported PlatformsEloquent Elusor is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 18.04 (Bionic):amd64andarm64Mac macOS 10.14 (Mojave)Windows 10 (Visual Studio 2019)Tier 2 platforms:Ubuntu 18.04 (Bionic):arm32Tier 3 platforms:Debian Stretch (9):amd64,arm64andarm32OpenEmbedded Thud (2.6) / webOS OSE:arm32andx86For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Eloquent ElusorNew features in this ROS 2 releaseA few features and improvements we would like to highlight:Support for markup-based launch files (XML/YAML)Improved launch-based testingPassing key-value parameters on CLISupport stream logging macrosPer-node logging- All stdout/stderr output from nodes are logged in ~/.rosros2doctorImproved performance of sourcing setup filesrviz:interactive markers,torque ring,tf message filtersrqt:parameter plugin,tf tree plugin,robot steering plugin(also backported to Dashing)turtlesim(also backported to Dashing)RMW implementations:API to loan message for zero copy, used byrmw_iceoryxFast RTPS 1.9.3New Tier-2 implementation:rmw_cyclonedds(also backported to Dashing)Environment variableROS_LOCALHOST_ONLYto limit communication to localhostMacOS Mojave SupportTracing instrumentationfor rcl and rclcppDuring the development theEloquent meta ticketon GitHub contains an up-to-date state of the ongoing high level tasks as well as references specific tickets with more details.Changes since the Dashing releasegeometry_msgsThegeometry_msgs/msg/Quaternion.msginterface now default initializes to a valid quaternion, with the following values:\[\begin{split}x = 0 \\ +y = 0 \\ +z = 0 \\ +w = 1\end{split}\]Here is the pull request for more detail:https://github.com/ros2/common_interfaces/pull/74Static transform broadcasters and listeners now use QoS durabilitytransient_localon the/tf_statictopic. +Similar to the latched setting in ROS 1, static transforms only need to be published once. +New listeners will receive transforms from all static broadcasters that are alive and have published before. +All publishers must be updated to use this durability setting or their messages won’t be received by transform listeners. +See this pull request for more detail:https://github.com/ros2/geometry2/pull/160rclcppAPI Break withget_actual_qos()Introduced in Dashing, theget_actual_qos()method on thePublisherBaseandSubscriptionBasepreviously returned an rmw type,rmw_qos_profile_t, but that made it awkward to reuse with the creation of other entities. +Therefore it was updated to return arclcpp::QoSinstead.Existing code will need to use therclcpp::QoS::get_rmw_qos_profile()method if the rmw profile is still required. +For example:voidmy_func(constrmw_qos_profile_t&rmw_qos);/* Previously: */// my_func(some_pub->get_actual_qos());/* Now: */my_func(some_pub->get_actual_qos()->get_rmw_qos_profile());The rationale for breaking this directly rather than doing a tick-tock is that it is a new function and is expected to be used infrequently by users. +Also, since only the return type is changing, adding a new function with a different would be to only way to do a deprecation cycle andget_actual_qos()is the most appropriate name, so we would be forced to pick a less obvious name for the method.API Break with Publisher and Subscription ClassesIn an effort to streamline the construction of Publishers and Subscriptions, the API of the constructors were changed.It would be impossible to support a deprecation cycle, because the old signature takes an rcl type and the new one takes theNodeBaseInterfacetype so that it can get additional information it now needs, and there’s no way to get the additional information needed from just the rcl type. +The new signature could possibly be backported if that would help contributors, but since the publishers and subscriptions are almost always created using the factory functions or some other higher level API, we do not expect this to be a problem for most users.Please see the original pr for more detail and comment there if this causes issues:https://github.com/ros2/rclcpp/pull/867Compiler warning about unused result ofadd_on_set_parameters_callbackSince Eloquent Patch Release 2 (2020-12-04)Users should retain the handle returned byrclcpp::Node::add_on_set_parameters_callback, otherwise their callback may be unregistered. +A warning has been added to help identify bugs where the returned handle is not used.https://github.com/ros2/rclcpp/pull/1243rmwAPI Break Due to Addition of Publisher and Subscription OptionsThermw_create_publisher()method had a new argument added of typeconstrmw_publisher_options_t*. +This new structure holds options (beyond the typesupport, topic name, and QoS) for new publishers.Thermw_create_subscription()method had one argument removed,boolignore_local_publications, and replaced by the new options of typeconstrmw_subscription_options_t*. +Theignore_local_publicationsoption was moved into the newrmw_subscription_options_ttype.In both cases the new argument, which are pointers, may never be null, and so the rmw implementations should check to make sure the options are not null. +Additionally, the options should be copied into the corresponding rmw structure.See this pull request, and the associated pull requests for more details:https://github.com/ros2/rmw/pull/187ros2cliros2msg and ros2srv deprecatedThe CLI toolsros2msgandros2srvare deprecated. +They have been replaced by the toolros2interface, which also supports action and IDL interfaces. +You can runros2interface--helpfor usage.ros2nodeService clients have been added to ros2node info. +As part of that change the Python functionros2node.api.get_service_infohas been renamed toros2node.api.get_service_server_info.rvizRenamed ‘2D Nav Goal’ toolThe tool was renamed to ‘2D Goal Pose’ and the default topic was changed from/move_base_simple/goalto/goal_pose.Here is the related pull request:https://github.com/ros2/rviz/pull/455TF2 BufferTF2 buffers now have to be given a timer interface.If a timer interface is not given, an exception will be thrown.For example:tf=std::make_shared(get_clock());// The next two lines are new in Eloquentautotimer_interface=std::make_shared(this->get_node_base_interface(),this->get_node_timers_interface());tf->setCreateTimerInterface(timer_interface);// Pass the Buffer to the TransformListener as beforetransform_listener=std::make_shared(*tf);rclROS command line argument changesTo cope with an increasingly complex interface, with a now extended set of configuration options, ROS CLI syntax has been changed. +As an example, a command line using Dashing syntax like:ros2 run some_package some_node foo:=bar __params:=/path/to/params.yaml __log_level:=WARN --user-flagis written using Eloquent (and onwards) syntax as:ros2 run some_package some_node --ros-args --remap foo:=bar --params-file /path/to/params.yaml --log-level WARN -- --user-flagThis explicit syntax affords new features, like single parameter assignment--paramname:=value. +For further reference and rationale, check theROS command line arguments design document.WarningFormer syntax has been deprecated and is due for removal in the next release.Known Issues[ros2/rosidl#402]find_package(PCL)interferes with ROS interface generation. +Workaround: invokefind_package(PCL)afterrosidl_generate_interfaces().[ros2/rclcpp#893]rclcpp::Contextis not destroyed because of a reference cycle withrclcpp::GraphListener. This causes a memory leak. A fix has not been backported because of the risk of breaking ABI.Timeline before the releaseA few milestones leading up to the release:Mon. Sep 30th (alpha)First releases of core packages available. +Testing can happen from now on (some features might not have landed yet).Fri. Oct 18thAPI and feature freeze for core packages +Only bug fix releases should be made after this point. +New packages can be released independently.Thu. Oct 24th (beta)Updated releases of core packages available. +Additional testing of the latest features.Wed. Nov 13th (release candidate)Updated releases of core packages available.Tue. Nov 19thFreeze rosdistro. +No PRs for Eloquent on therosdistrorepo will be merged (reopens after the release announcement). + +Code Examples: + +Language: unknown +voidmy_func(constrmw_qos_profile_t&rmw_qos);/* Previously: */// my_func(some_pub->get_actual_qos());/* Now: */my_func(some_pub->get_actual_qos()->get_rmw_qos_profile()); + +Language: unknown +tf=std::make_shared(get_clock());// The next two lines are new in Eloquentautotimer_interface=std::make_shared(this->get_node_base_interface(),this->get_node_timers_interface());tf->setCreateTimerInterface(timer_interface);// Pass the Buffer to the TransformListener as beforetransform_listener=std::make_shared(*tf); + +Language: unknown +ros2 run some_package some_node foo:=bar __params:=/path/to/params.yaml __log_level:=WARN --user-flag + +Language: unknown +ros2 run some_package some_node --ros-args --remap foo:=bar --params-file /path/to/params.yaml --log-level WARN -- --user-flag diff --git "a/exported_docs/ros2/Enabling_topic_statistics_(C++)\357\203\201.txt" "b/exported_docs/ros2/Enabling_topic_statistics_(C++)\357\203\201.txt" new file mode 100644 index 0000000..252daaf --- /dev/null +++ "b/exported_docs/ros2/Enabling_topic_statistics_(C++)\357\203\201.txt" @@ -0,0 +1,70 @@ +Title: Enabling topic statistics (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Topic-Statistics-Tutorial/Topic-Statistics-Tutorial.html +Section: Installation +-------------------------------------------------------------------------------- + +Enabling topic statistics (C++)Goal:Enable ROS 2 Topic Statistics and view the output statistics data.Tutorial level:AdvancedTime:10 minutesTable of ContentsBackgroundPrerequisitesTasks1 Write the subscriber node with statistics enabled1.1 Examine the code1.2 CMakeLists.txt2 Build and run3 Observe published statistic dataSummaryRelated contentBackgroundThis is a short tutorial on how to enable topic statistics in ROS 2 and view the published statistics output using command line tools (ros2topic).ROS 2 provides the integrated measurement of statistics for messages received by any subscription, +called Topic Statistics. +With Topic Statistics enabled for your subscription, you can characterize the performance of your +system or use the data to help diagnose any present issues.For more details please see theTopic Statistics Concepts Page.PrerequisitesAn installation from either binaries or source.In previous tutorials, you learned how tocreate a workspace,create a package, and create aC++publisher and subscriber.This tutorial assumes that you still have yourcpp_pubsubpackage from theC++tutorial.Tasks1 Write the subscriber node with statistics enabledNavigate into theros2_ws/src/cpp_pubsub/srcfolder, created in theprevious tutorial, and +download the example talker code by entering the following command:LinuxmacOSWindowswget -O member_function_with_topic_statistics.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/member_function_with_topic_statistics.cppwget -O member_function_with_topic_statistics.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/member_function_with_topic_statistics.cppRight click this link and select Save Aspublisher_member_function.cpp:https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/member_function_with_topic_statistics.cppNow there will be a new file namedmember_function_with_topic_statistics.cpp. +Open the file using your preferred text editor.#include#include#include"rclcpp/rclcpp.hpp"#include"rclcpp/subscription_options.hpp"#include"std_msgs/msg/string.hpp"classMinimalSubscriberWithTopicStatistics:publicrclcpp::Node{public:MinimalSubscriberWithTopicStatistics():Node("minimal_subscriber_with_topic_statistics"){// manually enable topic statistics via optionsautooptions=rclcpp::SubscriptionOptions();options.topic_stats_options.state=rclcpp::TopicStatisticsState::Enable;// configure the collection window and publish period (default 1s)options.topic_stats_options.publish_period=std::chrono::seconds(10);// configure the topic name (default '/statistics')// options.topic_stats_options.publish_topic = "/topic_statistics"autocallback=[this](std_msgs::msg::String::SharedPtrmsg){this->topic_callback(msg);};subscription_=this->create_subscription("topic",10,callback,options);}private:voidtopic_callback(conststd_msgs::msg::String::ConstSharedPtrmsg)const{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());}rclcpp::Subscription::SharedPtrsubscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}1.1 Examine the codeAs in theC++tutorial, we have a subscriber node which receives string messages from thetopictopic from thetopic_callbackfunction. +However, we’ve now added options to configure the subscription to enable topic statistics with +therclcpp::SubscriptionOptions()options struct.// manually enable topic statistics via optionsautooptions=rclcpp::SubscriptionOptions();options.topic_stats_options.state=rclcpp::TopicStatisticsState::Enable;Optionally, fields such as the statistics collection/publish period and the topic used to publish +statistics can be configured as well.// configure the collection window and publish period (default 1s)options.topic_stats_options.publish_period=std::chrono::seconds(10);// configure the topic name (default '/statistics')// options.topic_stats_options.publish_topic = "/my_topic"The configurable fields are described in the following table:Subscription Config FieldPurposetopic_stats_options.stateEnable or disable topic statistics (defaultrclcpp::TopicStatisticsState::Disable)topic_stats_options.publish_periodThe period in which to collect statistics data and publish a statistics message (default1s)topic_stats_options.publish_topicThe topic to use when publishing statistics data (default/statistics)1.2 CMakeLists.txtNow open theCMakeLists.txtfile.Add the executable and name itlistener_with_topic_statisticsso you can run your node usingros2run:add_executable(listener_with_topic_statistics src/member_function_with_topic_statistics.cpp)ament_target_dependencies(listener_with_topic_statistics rclcpp std_msgs)install(TARGETStalkerlistenerlistener_with_topic_statisticsDESTINATION lib/${PROJECT_NAME})Make sure to save the file, and then your pub/sub system, with topic statistics enabled, +should be ready for use.2 Build and runTo build, see theBuild and runsection in the pub/sub tutorial.Run the subscriber with statistics enabled node:ros2 run cpp_pubsub listener_with_topic_statisticsNow run the talker node:ros2 run cpp_pubsub talkerThe terminal should start publishing info messages every 0.5 seconds, like so:[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4"The listener will start printing messages to the console, starting at whatever message count the publisher is on at that time, like so:[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 10"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 11"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 12"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 13"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 14"Now that the subscriber node is receiving messages, it will periodically publish statistics messages. +We will observe these messages in the next section.3 Observe published statistic dataWhile the nodes are running, open a new terminal window. +Execute the following command:ros2 topic listThis will list all currently active topics. +You should see the following:/parameter_events/rosout/statistics/topicIf you optionally changed thetopic_stats_options.publish_topicfield earlier in the tutorial, +then you will see that name instead of/statistics.The subscriber node you created is publishing statistics, for the topictopic, to the output topic/statistics.We can visualize this usingRQtNow we can view the statistics data published to this topic with the following command:ros2 topic echo /statisticsThe terminal should start publishing statistics messages every 10 seconds, because thetopic_stats_options.publish_periodsubscription configuration was optionally changed earlier in the tutorial.---measurement_source_name: minimal_subscriber_with_topic_statisticsmetrics_source: message_ageunit: mswindow_start:sec: 1594856666nanosec: 931527366window_stop:sec: 1594856676nanosec: 930797670statistics:- data_type: 1data: .nan- data_type: 3data: .nan- data_type: 2data: .nan- data_type: 5data: 0.0- data_type: 4data: .nan---measurement_source_name: minimal_subscriber_with_topic_statisticsmetrics_source: message_periodunit: mswindow_start:sec: 1594856666nanosec: 931527366window_stop:sec: 1594856676nanosec: 930797670statistics:- data_type: 1data: 499.2746365105009- data_type: 3data: 500.0- data_type: 2data: 499.0- data_type: 5data: 619.0- data_type: 4data: 0.4463309283488427---From themessage definitionthedata_typesare as followsdata_type valuestatistics1average2minimum3maximum4standard deviation5sample countHere we see the two currently possible calculated statistics for thestd_msgs::msg::Stringmessage published +to/topicby theminimal_publisher. +Because thestd_msgs::msg::Stringdoes not have a message header, themessage_agecalculation cannot be performed, +so NaNs are returned. +However, themessage_periodcan be calculated and we see the statistics populated +in the message above.SummaryYou created a subscriber node with topic statistics enabled, which published statistics data from +theC++’s publisher node. You were able to compile and run this node. While running, +you were able to observe the statistics data.Related contentTo observe how themessage_ageperiod is calculated please see theROS 2 Topic Statistics demo. + +Code Examples: + +Language: unknown +wget -O member_function_with_topic_statistics.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/member_function_with_topic_statistics.cpp + +Language: unknown +wget -O member_function_with_topic_statistics.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/member_function_with_topic_statistics.cpp + +Language: unknown +#include#include#include"rclcpp/rclcpp.hpp"#include"rclcpp/subscription_options.hpp"#include"std_msgs/msg/string.hpp"classMinimalSubscriberWithTopicStatistics:publicrclcpp::Node{public:MinimalSubscriberWithTopicStatistics():Node("minimal_subscriber_with_topic_statistics"){// manually enable topic statistics via optionsautooptions=rclcpp::SubscriptionOptions();options.topic_stats_options.state=rclcpp::TopicStatisticsState::Enable;// configure the collection window and publish period (default 1s)options.topic_stats_options.publish_period=std::chrono::seconds(10);// configure the topic name (default '/statistics')// options.topic_stats_options.publish_topic = "/topic_statistics"autocallback=[this](std_msgs::msg::String::SharedPtrmsg){this->topic_callback(msg);};subscription_=this->create_subscription("topic",10,callback,options);}private:voidtopic_callback(conststd_msgs::msg::String::ConstSharedPtrmsg)const{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());}rclcpp::Subscription::SharedPtrsubscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +// manually enable topic statistics via optionsautooptions=rclcpp::SubscriptionOptions();options.topic_stats_options.state=rclcpp::TopicStatisticsState::Enable; + +Language: unknown +// configure the collection window and publish period (default 1s)options.topic_stats_options.publish_period=std::chrono::seconds(10);// configure the topic name (default '/statistics')// options.topic_stats_options.publish_topic = "/my_topic" + +Language: unknown +add_executable(listener_with_topic_statistics src/member_function_with_topic_statistics.cpp)ament_target_dependencies(listener_with_topic_statistics rclcpp std_msgs)install(TARGETStalkerlistenerlistener_with_topic_statisticsDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +ros2 run cpp_pubsub listener_with_topic_statistics + +Language: unknown +ros2 run cpp_pubsub talker + +Language: unknown +[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4" + +Language: unknown +[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 10"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 11"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 12"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 13"[INFO] [minimal_subscriber_with_topic_statistics]: I heard: "Hello World: 14" + +Language: unknown +ros2 topic list + +Language: unknown +/parameter_events/rosout/statistics/topic + +Language: unknown +ros2 topic echo /statistics + +Language: unknown +---measurement_source_name: minimal_subscriber_with_topic_statisticsmetrics_source: message_ageunit: mswindow_start:sec: 1594856666nanosec: 931527366window_stop:sec: 1594856676nanosec: 930797670statistics:- data_type: 1data: .nan- data_type: 3data: .nan- data_type: 2data: .nan- data_type: 5data: 0.0- data_type: 4data: .nan---measurement_source_name: minimal_subscriber_with_topic_statisticsmetrics_source: message_periodunit: mswindow_start:sec: 1594856666nanosec: 931527366window_stop:sec: 1594856676nanosec: 930797670statistics:- data_type: 1data: 499.2746365105009- data_type: 3data: 500.0- data_type: 2data: 499.0- data_type: 5data: 619.0- data_type: 4data: 0.4463309283488427--- diff --git "a/exported_docs/ros2/End-of-Life_Distributions\357\203\201.txt" "b/exported_docs/ros2/End-of-Life_Distributions\357\203\201.txt" new file mode 100644 index 0000000..c7551e1 --- /dev/null +++ "b/exported_docs/ros2/End-of-Life_Distributions\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: End-of-Life Distributions +URL: https://docs.ros.org/en/jazzy/Releases/End-of-Life.html +Section: Installation +-------------------------------------------------------------------------------- + +End-of-Life DistributionsBelow is a list of historic ROS 2 distributions that are no longer supported.Galactic Geochelone (galactic)Foxy Fitzroy (foxy)Eloquent Elusor (eloquent)Dashing Diademata (dashing)Crystal Clemmys (crystal)Bouncy Bolson (bouncy)Ardent Apalone (ardent)Beta 3 (r2b3)Beta 2 (r2b2)Beta 1 (Asphalt)Alphas \ No newline at end of file diff --git "a/exported_docs/ros2/Ensuring_security_across_machines\357\203\201.txt" "b/exported_docs/ros2/Ensuring_security_across_machines\357\203\201.txt" new file mode 100644 index 0000000..23939af --- /dev/null +++ "b/exported_docs/ros2/Ensuring_security_across_machines\357\203\201.txt" @@ -0,0 +1,47 @@ +Title: Ensuring security across machines +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Security/Security-on-Two.html +Section: Installation +-------------------------------------------------------------------------------- + +Ensuring security across machinesGoal:Make two different machines communicate securely.Tutorial level:AdvancedTime:5 minutesContentsBackgroundCreate the second keystoreCopy filesLaunch the nodesBackgroundBefore proceeding ensure you have completed theSetting up securitytutorial.The previous tutorials have used two ROS nodes on the same machine sending all network communications over the localhost interface. +Let’s extend that scenario to involve multiple machines, since the benefits of authentication and encryption then become more obvious.Suppose that the machine with the keystore created in the previous demo has a hostnameAlice, and that we want to also use another machine with hostnameBobfor our multi-machinetalker/listenerdemo. +We need to move some keys fromAlicetoBobto allow SROS 2 to authenticate and encrypt the transmissions.Create the second keystoreBegin by creating an empty keystore onBob; the keystore is actually just an empty directory:LinuxMacOSWindowssshBob +mkdir~/sros2_demoexitsshBob +mkdir~/sros2_demoexitssh BobmdC:\dev\ros2\sros2_demoexitCopy filesNext copy the keys and certificates for thetalkerprogram fromAlicetoBob. +Since the keys are just text files, we can usescpto copy them.LinuxMacOSWindowscd~/sros2_demo/demo_keystore +scp-rtalkerUSERNAME@Bob:~/sros2_demo/demo_keystorecd~/sros2_demo/demo_keystore +scp-rtalkerUSERNAME@Bob:~/sros2_demo/demo_keystorecdC:\dev\ros2\sros2_demo\demo_keystore +scp -r talker USERNAME@Bob:/dev/ros2/sros2_demo/demo_keystoreWarningNote that in this case the entire keystore is shared across the different machines which may not be the desired behavior, as it may result in a security risk. +Please refer toDeployment Guidelinesfor more information in this regard.That will be very quick, since it’s just copying some very small text files. +Now, we’re ready to run a multi-machine talker/listener demo!Launch the nodesOnce the environment is set up, run the talker onBob:ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talkerand launch the listener onAlice:ros2rundemo_nodes_pylistener--ros-args--enclave/talker_listener/listenerAlice will now be receiving encrypted messages from Bob.With two machines successfully communicating using both encryption and authentication, you can use the same procedure to add more machines to your ROS graph. + +Code Examples: + +Language: unknown +sshBob +mkdir~/sros2_demoexit + +Language: unknown +sshBob +mkdir~/sros2_demoexit + +Language: unknown +ssh BobmdC:\dev\ros2\sros2_demoexit + +Language: unknown +cd~/sros2_demo/demo_keystore +scp-rtalkerUSERNAME@Bob:~/sros2_demo/demo_keystore + +Language: unknown +cd~/sros2_demo/demo_keystore +scp-rtalkerUSERNAME@Bob:~/sros2_demo/demo_keystore + +Language: unknown +cdC:\dev\ros2\sros2_demo\demo_keystore +scp -r talker USERNAME@Bob:/dev/ros2/sros2_demo/demo_keystore + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker + +Language: unknown +ros2rundemo_nodes_pylistener--ros-args--enclave/talker_listener/listener diff --git "a/exported_docs/ros2/Examining_network_traffic\357\203\201.txt" "b/exported_docs/ros2/Examining_network_traffic\357\203\201.txt" new file mode 100644 index 0000000..b456ff4 --- /dev/null +++ "b/exported_docs/ros2/Examining_network_traffic\357\203\201.txt" @@ -0,0 +1,150 @@ +Title: Examining network traffic +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Security/Examine-Traffic.html +Section: Installation +-------------------------------------------------------------------------------- + +Examining network trafficGoal:Capture and examine raw ROS 2 network traffic.Tutorial level:AdvancedTime:20 minutesContentsOverviewPrerequisitesRun the demoInstalltcpdumpStart the talker and listenerDisplay unencrypted discovery packetsDisplay unencrypted data packetsEnable encryptionDisplay encrypted discovery packetsDisplay encrypted data packetsOverviewROS 2 communications security is all about protecting communications between nodes. +Prior tutorials enabled security, but how can youreallytell if traffic is being encrypted? +In this tutorial we’ll take a look at capturing live network traffic to show the difference between encrypted and unencrypted traffic.Notermw_fastrtps_cppusesShared Memory Transportby default to improve the performance in the transport layer when the endpoints are in the same host system. +Security enclaves are still applied, and data will be encrypted. +However, you cannot capture live network traffic since the data will not be on the network interface. +If you are usingrmw_fastrtps_cpp, you need to either go through this tutorial and use a different host system between the publisher and subscriber, or disable shared memory transport withEnabling UDP TransportandHow to set Fast-DDS XML configuration.PrerequisitesThis guide only runs on Linux, and assumes you have alreadyinstalled ROS 2.Run the demoInstalltcpdumpBegin in a new terminal window by installingtcpdump, a command-line tool for capturing and displaying network traffic. +Although this tutorial describestcpdumpcommands, you can also useWireshark, a similar graphical tool for capturing and analyzing traffic.sudoaptupdate +sudoaptinstalltcpdumpRun following commands on a single machine through multiplesshsessions.Start the talker and listenerStart both the talker and the listener again, each in its own terminal. +The security environment variables are not set so security is not enabled for these sessions.# Disable ROS Security for both terminalsunsetROS_SECURITY_ENABLE# In terminal 1:ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker# In terminal 2:ros2rundemo_nodes_cpplistener--ros-args--enclave/talker_listener/listenerDisplay unencrypted discovery packetsWith the talker and listener running, open another terminal and starttcpdumpto look at the network traffic. +You need to usesudosince reading raw network traffic is a privileged operation.The command below uses the-Xoption to print packet contents, the-ioption to listen for packets on any interface, and captures onlyUDPport 7400 traffic.sudotcpdump-X-ianyudpport7400You should see packets like the following:20:18:04.400770 IP 8_xterm.46392 > 239.255.0.1.7400: UDP, length 252 + 0x0000: 4500 0118 d48b 4000 0111 7399 c0a8 8007 E.....@...s..... + 0x0010: efff 0001 b538 1ce8 0104 31c6 5254 5053 .....8....1.RTPS + ... + 0x00c0: 5800 0400 3f0c 3f0c 6200 1c00 1800 0000 X...?.?.b....... + 0x00d0: 2f74 616c 6b65 725f 6c69 7374 656e 6572 /talker_listener + 0x00e0: 2f74 616c 6b65 7200 2c00 2800 2100 0000 /talker.,.(.!... + 0x00f0: 656e 636c 6176 653d 2f74 616c 6b65 725f enclave=/talker_ + 0x0100: 6c69 7374 656e 6572 2f74 616c 6b65 723b listener/talker; + 0x0110: 0000 0000 0100 0000 ........This is a discovery datagram–the talker looking for subscribers. +As you can see, the node name (/talker_listener/talker) and the enclave (also/talker_listener/talker) are passed in plain text. +You should also see similar discovery datagrams from thelistenernode. +Some other features of a typical discovery packet:The destination address is 239.255.0.1, which is a multicast IP address; ROS 2 uses multicast traffic for discovery by default.UDP 7400 is the destination port, as per theDDS-RTPS specification.The packet contains the “RTPS” tag, also as defined to the DDS-RTPS specification.Display unencrypted data packetsUsetcpdumpto capture non-discovery RTPS packets by filtering on UDP ports above 7400:sudotcpdump-iany-Xudpportrange7401-7500You will see few different types of packets, but watch for something like the following which is obviously data being sent from a talker to a listener:20:49:17.927303 IP localhost.46392 > localhost.7415: UDP, length 84 + 0x0000: 4500 0070 5b53 4000 4011 e127 7f00 0001 E..p[S@.@..'.... + 0x0010: 7f00 0001 b538 1cf7 005c fe6f 5254 5053 .....8...\.oRTPS + 0x0020: 0203 010f 010f 4874 e752 0000 0100 0000 ......Ht.R...... + 0x0030: 0901 0800 cdee b760 5bf3 5aed 1505 3000 .......`[.Z...0. + 0x0040: 0000 1000 0000 1204 0000 1203 0000 0000 ................ + 0x0050: 5708 0000 0001 0000 1200 0000 4865 6c6c W...........Hell + 0x0060: 6f20 576f 726c 643a 2032 3133 3500 0000 o.World:.2135...Some features to note about this packet:The message contents, “Hello World: 2135”, are sent in clear textThe source and destination IP address islocalhost: since both nodes are running on the same machine, the nodes discovered each other on thelocalhostinterfaceEnable encryptionStop both the talker and the listener nodes. +Enable encryption for both by setting the security environment variables and run them again.# In terminal 1:exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforce +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker# In terminal 2:exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforce +ros2rundemo_nodes_cpplistener--ros-args--enclave/talker_listener/listenerDisplay encrypted discovery packetsRun the sametcpdumpcommand used earlier to examine the output of discovery traffic with encryption enabled:sudotcpdump-X-ianyudpport7400The typical discovery packet looks somewhat like the following:21:09:07.336617 IP 8_xterm.60409 > 239.255.0.1.7400: UDP, length 596 + 0x0000: 4500 0270 c2f6 4000 0111 83d6 c0a8 8007 E..p..@......... + 0x0010: efff 0001 ebf9 1ce8 025c 331e 5254 5053 .........\3.RTPS + 0x0020: 0203 010f bbdd 199c 7522 b6cb 699f 74ae ........u"..i.t. + ... + 0x00c0: 5800 0400 3f0c ff0f 6200 2000 1a00 0000 X...?...b....... + 0x00d0: 2f74 616c 6b65 725f 6c69 7374 656e 6572 /talker_listener + 0x00e0: 2f6c 6973 7465 6e65 7200 0000 2c00 2800 /listener...,.(. + 0x00f0: 2300 0000 656e 636c 6176 653d 2f74 616c #...enclave=/tal + 0x0100: 6b65 725f 6c69 7374 656e 6572 2f6c 6973 ker_listener/lis + 0x0110: 7465 6e65 723b 0000 0110 c400 1400 0000 tener;.......... + 0x0120: 4444 533a 4175 7468 3a50 4b49 2d44 483a DDS:Auth:PKI-DH: + 0x0130: 312e 3000 0400 0000 0c00 0000 6464 732e 1.0.........dds. + ... + 0x0230: 1100 0000 6464 732e 7065 726d 5f63 612e ....dds.perm_ca. + 0x0240: 616c 676f 0000 0000 0d00 0000 4543 4453 algo........ECDS + 0x0250: 412d 5348 4132 3536 0000 0000 0000 0000 A-SHA256........ + 0x0260: 0510 0800 0700 0080 0600 0080 0100 0000 ................This packet is much larger and includes information which can be used to set up encryption among ROS nodes. +As we will see shortly, this actually includes some of the security configuration files that were created when we enabled security. +Interested in learning more? Take a look at the excellent paperNetwork Reconnaissance and Vulnerability Excavation of Secure DDS Systemsto understand why this matters.Display encrypted data packetsNow usetcpdumpto capture data packets:sudotcpdump-iany-Xudpportrange7401-7500A typical data packet looks like the following:21:18:14.531102 IP localhost.54869 > localhost.7415: UDP, length 328 + 0x0000: 4500 0164 bb42 4000 4011 8044 7f00 0001 E..d.B@.@..D.... + 0x0010: 7f00 0001 d655 1cf7 0150 ff63 5254 5053 .....U...P.cRTPS + 0x0020: 0203 010f daf7 10ce d977 449b bb33 f04a .........wD..3.J + 0x0030: 3301 1400 0000 0003 492a 6066 8603 cdb5 3.......I*`f.... + 0x0040: 9df6 5da6 8402 2136 0c01 1400 0000 0000 ..]...!6........ + 0x0050: 0203 010f daf7 10ce d977 449b bb33 f04a .........wD..3.J + ... + 0x0130: 7905 d390 3201 1400 3ae5 0b60 3906 967e y...2...:..`9..~ + 0x0140: 5b17 fd42 de95 54b9 0000 0000 3401 1400 [..B..T.....4... + 0x0150: 42ae f04d 0559 84c5 7116 1c51 91ba 3799 B..M.Y..q..Q..7. + 0x0160: 0000 0000 ....The data in this RTPS packet is all encrypted.In addition to this data packet, you should see additional packets with node and enclave names; these support other ROS features such as parameters and services. +Encryption options for these packets can also be controlled by security policy. + +Code Examples: + +Language: unknown +sudoaptupdate +sudoaptinstalltcpdump + +Language: unknown +# Disable ROS Security for both terminalsunsetROS_SECURITY_ENABLE# In terminal 1:ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker# In terminal 2:ros2rundemo_nodes_cpplistener--ros-args--enclave/talker_listener/listener + +Language: unknown +sudotcpdump-X-ianyudpport7400 + +Language: unknown +20:18:04.400770 IP 8_xterm.46392 > 239.255.0.1.7400: UDP, length 252 + 0x0000: 4500 0118 d48b 4000 0111 7399 c0a8 8007 E.....@...s..... + 0x0010: efff 0001 b538 1ce8 0104 31c6 5254 5053 .....8....1.RTPS + ... + 0x00c0: 5800 0400 3f0c 3f0c 6200 1c00 1800 0000 X...?.?.b....... + 0x00d0: 2f74 616c 6b65 725f 6c69 7374 656e 6572 /talker_listener + 0x00e0: 2f74 616c 6b65 7200 2c00 2800 2100 0000 /talker.,.(.!... + 0x00f0: 656e 636c 6176 653d 2f74 616c 6b65 725f enclave=/talker_ + 0x0100: 6c69 7374 656e 6572 2f74 616c 6b65 723b listener/talker; + 0x0110: 0000 0000 0100 0000 ........ + +Language: unknown +sudotcpdump-iany-Xudpportrange7401-7500 + +Language: unknown +20:49:17.927303 IP localhost.46392 > localhost.7415: UDP, length 84 + 0x0000: 4500 0070 5b53 4000 4011 e127 7f00 0001 E..p[S@.@..'.... + 0x0010: 7f00 0001 b538 1cf7 005c fe6f 5254 5053 .....8...\.oRTPS + 0x0020: 0203 010f 010f 4874 e752 0000 0100 0000 ......Ht.R...... + 0x0030: 0901 0800 cdee b760 5bf3 5aed 1505 3000 .......`[.Z...0. + 0x0040: 0000 1000 0000 1204 0000 1203 0000 0000 ................ + 0x0050: 5708 0000 0001 0000 1200 0000 4865 6c6c W...........Hell + 0x0060: 6f20 576f 726c 643a 2032 3133 3500 0000 o.World:.2135... + +Language: unknown +# In terminal 1:exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforce +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker# In terminal 2:exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforce +ros2rundemo_nodes_cpplistener--ros-args--enclave/talker_listener/listener + +Language: unknown +sudotcpdump-X-ianyudpport7400 + +Language: unknown +21:09:07.336617 IP 8_xterm.60409 > 239.255.0.1.7400: UDP, length 596 + 0x0000: 4500 0270 c2f6 4000 0111 83d6 c0a8 8007 E..p..@......... + 0x0010: efff 0001 ebf9 1ce8 025c 331e 5254 5053 .........\3.RTPS + 0x0020: 0203 010f bbdd 199c 7522 b6cb 699f 74ae ........u"..i.t. + ... + 0x00c0: 5800 0400 3f0c ff0f 6200 2000 1a00 0000 X...?...b....... + 0x00d0: 2f74 616c 6b65 725f 6c69 7374 656e 6572 /talker_listener + 0x00e0: 2f6c 6973 7465 6e65 7200 0000 2c00 2800 /listener...,.(. + 0x00f0: 2300 0000 656e 636c 6176 653d 2f74 616c #...enclave=/tal + 0x0100: 6b65 725f 6c69 7374 656e 6572 2f6c 6973 ker_listener/lis + 0x0110: 7465 6e65 723b 0000 0110 c400 1400 0000 tener;.......... + 0x0120: 4444 533a 4175 7468 3a50 4b49 2d44 483a DDS:Auth:PKI-DH: + 0x0130: 312e 3000 0400 0000 0c00 0000 6464 732e 1.0.........dds. + ... + 0x0230: 1100 0000 6464 732e 7065 726d 5f63 612e ....dds.perm_ca. + 0x0240: 616c 676f 0000 0000 0d00 0000 4543 4453 algo........ECDS + 0x0250: 412d 5348 4132 3536 0000 0000 0000 0000 A-SHA256........ + 0x0260: 0510 0800 0700 0080 0600 0080 0100 0000 ................ + +Language: unknown +sudotcpdump-iany-Xudpportrange7401-7500 + +Language: unknown +21:18:14.531102 IP localhost.54869 > localhost.7415: UDP, length 328 + 0x0000: 4500 0164 bb42 4000 4011 8044 7f00 0001 E..d.B@.@..D.... + 0x0010: 7f00 0001 d655 1cf7 0150 ff63 5254 5053 .....U...P.cRTPS + 0x0020: 0203 010f daf7 10ce d977 449b bb33 f04a .........wD..3.J + 0x0030: 3301 1400 0000 0003 492a 6066 8603 cdb5 3.......I*`f.... + 0x0040: 9df6 5da6 8402 2136 0c01 1400 0000 0000 ..]...!6........ + 0x0050: 0203 010f daf7 10ce d977 449b bb33 f04a .........wD..3.J + ... + 0x0130: 7905 d390 3201 1400 3ae5 0b60 3906 967e y...2...:..`9..~ + 0x0140: 5b17 fd42 de95 54b9 0000 0000 3401 1400 [..B..T.....4... + 0x0150: 42ae f04d 0559 84c5 7116 1c51 91ba 3799 B..M.Y..q..Q..7. + 0x0160: 0000 0000 .... diff --git "a/exported_docs/ros2/Executors\357\203\201.txt" "b/exported_docs/ros2/Executors\357\203\201.txt" new file mode 100644 index 0000000..6384c5a --- /dev/null +++ "b/exported_docs/ros2/Executors\357\203\201.txt" @@ -0,0 +1,57 @@ +Title: Executors +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Executors.html +Section: Installation +-------------------------------------------------------------------------------- + +ExecutorsTable of ContentsOverviewBasic useTypes of ExecutorsCallback groupsScheduling semanticsOutlookFurther informationOverviewExecution management in ROS 2 is handled by Executors. +An Executor uses one or more threads of the underlying operating system to invoke the callbacks of subscriptions, timers, service servers, action servers, etc. on incoming messages and events. +The explicit Executor class (inexecutor.hppin rclcpp, inexecutors.pyin rclpy, or inexecutor.hin rclc) provides more control over execution management than the spin mechanism in ROS 1, although the basic API is very similar.In the following, we focus on the C++ Client Libraryrclcpp.Basic useIn the simplest case, the main thread is used for processing the incoming messages and events of a Node by callingrclcpp::spin(..)as follows:intmain(intargc,char*argv[]){// Some initialization.rclcpp::init(argc,argv);...// Instantiate a node.rclcpp::Node::SharedPtrnode=...// Run the executor.rclcpp::spin(node);// Shutdown and exit....return0;}The call tospin(node)basically expands to an instantiation and invocation of the Single-Threaded Executor, which is the simplest Executor:rclcpp::executors::SingleThreadedExecutorexecutor;executor.add_node(node);executor.spin();By invokingspin()of the Executor instance, the current thread starts querying the rcl and middleware layers for incoming messages and other events and calls the corresponding callback functions until the node shuts down. +In order not to counteract the QoS settings of the middleware, an incoming message is not stored in a queue on the Client Library layer but kept in the middleware until it is taken for processing by a callback function. +(This is a crucial difference to ROS 1.) +Await setis used to inform the Executor about available messages on the middleware layer, with one binary flag per queue. +Thewait setis also used to detect when timers expire.The Single-Threaded Executor is also used by the container process forcomponents, i.e. in all cases where nodes are created and executed without an explicit main function.Types of ExecutorsCurrently, rclcpp provides three Executor types, derived from a shared parent class:TheMulti-Threaded Executorcreates a configurable number of threads to allow for processing multiple messages or events in parallel. +TheStatic Single-Threaded Executoroptimizes the runtime costs for scanning the structure of a node in terms of subscriptions, timers, service servers, action servers, etc. +It performs this scan only once when the node is added, while the other two executors regularly scan for such changes. +Therefore, the Static Single-Threaded Executor should be used only with nodes that create all subscriptions, timers, etc. during initialization.All three executors can be used with multiple nodes by callingadd_node(..)for each node.rclcpp::Node::SharedPtrnode1=...rclcpp::Node::SharedPtrnode2=...rclcpp::Node::SharedPtrnode3=...rclcpp::executors::StaticSingleThreadedExecutorexecutor;executor.add_node(node1);executor.add_node(node2);executor.add_node(node3);executor.spin();In the above example, the one thread of a Static Single-Threaded Executor is used to serve three nodes together. +In case of a Multi-Threaded Executor, the actual parallelism depends on the callback groups.Callback groupsROS 2 allows organizing the callbacks of a node in groups. +In rclcpp, such acallback groupcan be created by thecreate_callback_groupfunction of the Node class. +In rclpy, the same is done by calling the constructor of the specific callback group type. +The callback group must be stored throughout execution of the node (eg. as a class member), or otherwise the executor won’t be able to trigger the callbacks. +Then, this callback group can be specified when creating a subscription, timer, etc. - for example by the subscription options:C++Pythonmy_callback_group=create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);rclcpp::SubscriptionOptionsoptions;options.callback_group=my_callback_group;my_subscription=create_subscription("/topic",rclcpp::SensorDataQoS(),callback,options);my_callback_group=MutuallyExclusiveCallbackGroup()my_subscription=self.create_subscription(Int32,"/topic",self.callback,qos_profile=1,callback_group=my_callback_group)All subscriptions, timers, etc. that are created without the indication of a callback group are assigned to thedefault callback group. +The default callback group can be queried viaNodeBaseInterface::get_default_callback_group()in rclcpp +and byNode.default_callback_groupin rclpy.There are two types of callback groups, where the type has to be specified at instantiation time:Mutually exclusive:Callbacks of this group must not be executed in parallel.Reentrant:Callbacks of this group may be executed in parallel.Callbacks of different callback groups may always be executed in parallel. +The Multi-Threaded Executor uses its threads as a pool to process as many callbacks as possible in parallel according to these conditions. +For tips on how to use callback groups efficiently, seeUsing Callback Groups.The Executor base class in rclcpp also has the functionadd_callback_group(..), which allows distributing callback groups to different Executors. +By configuring the underlying threads using the operating system scheduler, specific callbacks can be prioritized over other callbacks. +For example, the subscriptions and timers of a control loop can be prioritized over all other subscriptions and standard services of a node. +Theexamples_rclcpp_cbg_executor packageprovides a demo of this mechanism.Scheduling semanticsIf the processing time of the callbacks is shorter than the period with which messages and events occur, the Executor basically processes them in FIFO order. +However, if the processing time of some callbacks is longer, messages and events will be queued on the lower layers of the stack. +The wait set mechanism reports only very little information about these queues to the Executor. +In detail, it only reports whether there are any messages for a certain topic or not. +The Executor uses this information to process the messages (including services and actions) in a round-robin fashion - but not in FIFO order. +The following flow diagram visualizes this scheduling semantics.This semantics was first described in apaper by Casini et al. at ECRTS 2019. +(Note: The paper also explains that timer events are prioritized over all other messages.This prioritization was removed in Eloquent.)OutlookWhile the three Executors of rclcpp work well for most applications, there are some issues that make them not suitable for real-time applications, which require well-defined execution times, determinism, and custom control over the execution order. +Here is a summary of some of these issues:Complex and mixed scheduling semantics. +Ideally you want well defined scheduling semantics to perform a formal timing analysis.Callbacks may suffer from priority inversion. +Higher priority callbacks may be blocked by lower priority callbacks.No explicit control over the callbacks execution order.No built-in control over triggering for specific topics.Additionally, the executor overhead in terms of CPU and memory usage is considerable. +The Static Single-Threaded Executor reduces this overhead greatly but it might not be enough for some applications.These issues have been partially addressed by the following developments:rclcpp WaitSet: TheWaitSetclass of rclcpp allows waiting directly on subscriptions, timers, service servers, action servers, etc. instead of using an Executor. +It can be used to implement deterministic, user-defined processing sequences, possibly processing multiple messages from different subscriptions together. +Theexamples_rclcpp_wait_set packageprovides several examples for the use of this user-level wait set mechanism.rclc Executor: This Executor from the C Client Libraryrclc, developed for micro-ROS, gives the user fine-grained control over the execution order of callbacks and allows for custom trigger conditions to activate callbacks. +Furthermore, it implements ideas of the Logical Execution Time (LET) semantics.Further informationMichael Pöhnl et al.:“ROS 2 Executor: How to make it efficient, real-time and deterministic?”. Workshop at ROS World 2021. Virtual event. 19 October 2021.Ralph Lange:“Advanced Execution Management with ROS 2”. ROS Industrial Conference. Virtual event. 16 December 2020.Daniel Casini, Tobias Blass, Ingo Lütkebohle, and Björn Brandenburg:“Response-Time Analysis of ROS 2 Processing Chains under Reservation-Based Scheduling”, Proc. of 31st ECRTS 2019, Stuttgart, Germany, July 2019. + +Code Examples: + +Language: unknown +intmain(intargc,char*argv[]){// Some initialization.rclcpp::init(argc,argv);...// Instantiate a node.rclcpp::Node::SharedPtrnode=...// Run the executor.rclcpp::spin(node);// Shutdown and exit....return0;} + +Language: unknown +rclcpp::executors::SingleThreadedExecutorexecutor;executor.add_node(node);executor.spin(); + +Language: unknown +rclcpp::Node::SharedPtrnode1=...rclcpp::Node::SharedPtrnode2=...rclcpp::Node::SharedPtrnode3=...rclcpp::executors::StaticSingleThreadedExecutorexecutor;executor.add_node(node1);executor.add_node(node2);executor.add_node(node3);executor.spin(); + +Language: unknown +my_callback_group=create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);rclcpp::SubscriptionOptionsoptions;options.callback_group=my_callback_group;my_subscription=create_subscription("/topic",rclcpp::SensorDataQoS(),callback,options); + +Language: unknown +my_callback_group=MutuallyExclusiveCallbackGroup()my_subscription=self.create_subscription(Int32,"/topic",self.callback,qos_profile=1,callback_group=my_callback_group) diff --git "a/exported_docs/ros2/Experimenting_with_a_dummy_robot\357\203\201.txt" "b/exported_docs/ros2/Experimenting_with_a_dummy_robot\357\203\201.txt" new file mode 100644 index 0000000..1d32f8f --- /dev/null +++ "b/exported_docs/ros2/Experimenting_with_a_dummy_robot\357\203\201.txt" @@ -0,0 +1,21 @@ +Title: Experimenting with a dummy robot +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos/dummy-robot-demo.html +Section: Installation +-------------------------------------------------------------------------------- + +Experimenting with a dummy robotIn this demo, we present a simple demo robot with all components from publishing joint states over publishing fake laser data until visualizing the robot model on a map in RViz.Launching the demoWe assume your ROS 2 installation dir as~/ros2_ws. Please change the directories according to your platform.To start the demo, we execute the demo bringup launch file, which we are going to explain in more details in the next section.Source Builddeb Packagemkdir -p ~/ros2_ws/src +cd ~/ros2_ws/src +git clone -b ${ROS_DISTRO}https://github.com/ros2/demoscd .. && colcon build –packages-up-to dummy_robot_bringup +source ~/ros2_ws/install/setup.bash +ros2 launch dummy_robot_bringup dummy_robot_bringup_launch.pysudo apt install ros-${ROS_DISTRO}-dummy-robot-bringup +ros2 launch dummy_robot_bringup dummy_robot_bringup_launch.pyYou should see some prints inside your terminal along the lines of the following:[INFO][launch]:DefaultloggingverbosityissettoINFO[INFO][dummy_map_server-1]:processstartedwithpid[2922][INFO][robot_state_publisher-2]:processstartedwithpid[2923][INFO][dummy_joint_states-3]:processstartedwithpid[2924][INFO][dummy_laser-4]:processstartedwithpid[2925][dummy_laser-4][INFO][1714837459.645517297][dummy_laser]:angleinc:0.004363[dummy_laser-4][INFO][1714837459.645613393][dummy_laser]:scansize:1081[dummy_laser-4][INFO][1714837459.645626640][dummy_laser]:scantimeincrement:0.000000[robot_state_publisher-2][INFO][1714837459.652977937][robot_state_publisher]:RobotinitializedIf you now open RViz2 in a new terminal, you’ll see your robot. 🎉$source~/ros2_ws/install/setup.bash +$rviz2This opens RViz2. Assuming you have your dummy_robot_bringup still launched, you can now add the TF display plugin and configure your global frame toworld. Once you did that, you should see a similar picture:What’s happening?If you have a closer look at the launch file, we start a couple of nodes at the same time.dummy_map_serverdummy_laserdummy_joint_statesrobot_state_publisherThe first two packages are relatively simple. Thedummy_map_serverconstantly publishes an empty map with a periodic update. Thedummy_laserdoes basically the same; publishing dummy fake laser scans.Thedummy_joint_statesnode is publishing fake joint state data. As we are publishing a simple RRbot with only two joints, this node publishes joint states values for these two joints.Therobot_state_publisheris doing the actual interesting work. It parses the given URDF file, extracts the robot model and listens to the incoming joint states. With this information, it publishes TF values for our robot which we visualize in RViz.Hooray! + +Code Examples: + +Language: unknown +[INFO][launch]:DefaultloggingverbosityissettoINFO[INFO][dummy_map_server-1]:processstartedwithpid[2922][INFO][robot_state_publisher-2]:processstartedwithpid[2923][INFO][dummy_joint_states-3]:processstartedwithpid[2924][INFO][dummy_laser-4]:processstartedwithpid[2925][dummy_laser-4][INFO][1714837459.645517297][dummy_laser]:angleinc:0.004363[dummy_laser-4][INFO][1714837459.645613393][dummy_laser]:scansize:1081[dummy_laser-4][INFO][1714837459.645626640][dummy_laser]:scantimeincrement:0.000000[robot_state_publisher-2][INFO][1714837459.652977937][robot_state_publisher]:Robotinitialized + +Language: unknown +$source~/ros2_ws/install/setup.bash +$rviz2 diff --git "a/exported_docs/ros2/Features_Status\357\203\201.txt" "b/exported_docs/ros2/Features_Status\357\203\201.txt" new file mode 100644 index 0000000..4eaf83e --- /dev/null +++ "b/exported_docs/ros2/Features_Status\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: Features Status +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Features.html +Section: Installation +-------------------------------------------------------------------------------- + +Features StatusThe features listed below are available in the current ROS 2 release. +Unless otherwise specified, the features are available for all supported platforms (Ubuntu 24.04 (Noble), Windows 10), DDS implementations (eProsima Fast DDS, RTI Connext DDS, and Eclipse Cyclone DDS) and programming language client libraries (C++ and Python). +For planned future development, see theRoadmap.FunctionalityLinkFine printDiscovery, transport and serialization over DDSArticleSupport formultiple DDS implementations, chosen at runtimeConcept,How-to GuideCurrently Eclipse Cyclone DDS, eProsima Fast DDS, and RTI Connext DDS are fully supported.Common core client library that is wrapped by language-specific librariesDetailsPublish/subscribe over topicsSample code,ArticleClients and servicesSample codeSet/retrieve parametersSample codeROS 1 - ROS 2 communication bridgeTutorialAvailable for topics and services, not yet available for actions.Quality of service settings for handling non-ideal networksDemoInter- and intra-process communication using the same APIDemoCurrently only in C++.Composition of node components at compile, link, load, or run timeDemoCurrently only in C++.Multiple executors (at level of callback groups) in same nodeDemoOnly in C++.Support for nodes with managed lifecyclesDemoCurrently only in C++.DDS-Security supportDemoCommand-line introspection tools using an extensible frameworkConceptLaunch system for coordinating multiple nodesTutorialNamespace support for nodes and topicsArticleStatic remapping of ROS namesHow-to GuideDemos of an all-ROS 2 mobile robotDemoPreliminary support for real-time codeDemo,demoLinux only. Not available for Fast RTPS.Preliminary support for “bare-metal” microcontrollersWikiContent filtering subscriptionDemoCurrently only in C++.Service IntrospectionDemoBesides core features of the platform, the biggest impact of ROS comes from its available packages. +The following are a few high-profile packages which are available in the latest release:gazebo_ros_pkgsimage_transportnavigation2rosbag2RQtRViz2 \ No newline at end of file diff --git "a/exported_docs/ros2/First_Time_Release\357\203\201.txt" "b/exported_docs/ros2/First_Time_Release\357\203\201.txt" new file mode 100644 index 0000000..cf7c91e --- /dev/null +++ "b/exported_docs/ros2/First_Time_Release\357\203\201.txt" @@ -0,0 +1,57 @@ +Title: First Time Release +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Releasing/First-Time-Release.html +Section: Installation +-------------------------------------------------------------------------------- + +First Time ReleaseThis guide explains how to release ROS 2 packages that you have not released before. +Due to numerous options available when releasing ROS packages, this guide intends to cover the most common scenario and does not cover every corner-case.Table of ContentsBe part of a release teamCreate a new release repositoryInstall dependenciesSet Up a Personal Access TokenEnsure repositories are up-to-dateGenerate ChangelogBump the package versionBloom ReleaseNext StepsBe part of a release teamYou must be part of arelease team. +If you are not part of a release team yet, follow either:Join a release teamStart a new release teamCreate a new release repositoryYou need arelease repositoryto release a package. +FollowCreate a new release repository.Install dependenciesInstall tools that you will use in the upcoming steps according to your platform:deb (eg. Ubuntu)RPM (eg. RHEL)Othersudoaptinstallpython3-bloompython3-catkin-pkgsudodnfinstallpython3-bloompython3-catkin_pkgpip3install-Ubloomcatkin_pkgMake sure you have rosdep initialized:sudorosdepinit +rosdepupdateNote that therosdepinitcommand may fail if it has already been initialized in the past; this can safely be ignored.Set Up a Personal Access TokenWarningIf the file~/.config/bloomexists on your computer, it is likely that you have done this before so you should skip this section.During the release process, multiple HTTPS Git operations will be performed that require password authentication. +To avoid being repeatedly asked for a password, aPersonal Access Token (PAT)will be set up. +If you have multi-factor authentication setup on your GitHub account, youmustsetup a Personal Access Token.Create a Personal Access Token by:Log in to GitHub and go toPersonal access tokens.Click theGenerate new tokenbutton.In the dropdown, selectGenerate new token (classic)SetNoteto something likeBloomtoken.SetExpirationtoNo expiration.Tick thepublic_repoandworkflowcheckboxes.Click theGenerate tokenbutton.After you have created the token, you will end up back at thePersonal access tokenspage.Copy the alphanumeric tokenthat is highlighted in green.Save your GitHub username and PAT to a new file called~/.config/bloom, with the format below:{ + "github_user": "", + "oauth_token": "" +}Ensure repositories are up-to-dateMake sure that:Your repository is hosted on a remote such as GitHub.You have a clone of the repository on your computer and are on the right branch.Both the remote repository and your clone are up-to-date.Generate ChangelogGenerate aCHANGELOG.rstfile per package in your repo using the following command:catkin_generate_changelog--allOpen allCHANGELOG.rstfiles in an editor. +You will see thatcatkin_generate_changeloghas auto-generated a forthcoming section with notes from commit messages:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Changelog for package your_package^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Forthcoming-----------*you can modify this commit message*and thisClean up the list of commit messages to concisely convey the notable changes that have been made to the packages since the last release, andcommit all the CHANGELOG.rst files.Do not modify theForthcomingheader.Bump the package versionEvery release of the package must have a unique version number higher than the previous release. +Run:catkin_prepare_releasewhich performs the following:increases the package version inpackage.xmlreplaces the headingForthcomingwithversion(date)(eg.0.0.1(2022-01-08)) inCHANGELOG.rstcommits those changescreates a tag (eg.0.0.1)pushes the changes and the tag to your remote repositoryNoteBy default the patch version of the package is incremented, such as from0.0.0to0.0.1. +To increment the minor or major version instead, runcatkin_prepare_release--bumpminororcatkin_prepare_release--bumpmajor. +For more details, seecatkin_prepare_release--help.Bloom ReleaseRun the following command, replacingmy_repowith the name of your repository:bloom-release--new-track--rosdistrojazzy--trackjazzymy_repoTip--new-tracktells bloom to create a newtrackand configure it.--rosdistrojazzyindicates that this release is for thejazzydistro--trackjazzyindicates that you want the track name to bejazzyYou will be prompted to enter information to configure a new track. +In a common scenario such as:Your packages are in a repository calledmy_repoYou are releasing a branch calledmainThe repository is hosted on GitHub athttps://github.com/my_organization/my_repo.gitYour release repository is athttps://github.com/ros2-gbp/my_repo-release.gitYou should respond to the prompts as following:ConfigurationValueRelease Repository urlhttps://github.com/ros2-gbp/my_repo-release.gitRepository Namemy_repoUpstream Repository URIhttps://github.com/my_organization/my_repo.gitUpstream VCS TypeVersionRelease TagUpstream Devel BranchmainROS DistroPatches DirectoryRelease Repository Push URLNoteAn empty cell in the table indicates that the default value should be used. +Simply respond to the prompt by pressing Enter.Bloom will automatically create a pull request for you againstrosdistro.Next StepsOnce your pull request has been submitted, usually within one or two days, one of the maintainers of rosdistro will review and merge your Pull Request. +If your package build is successful, in 24-48 hours your packages will become available in theros-testingrepository, where you cantest your pre-release binaries.Approximately every two to four weeks, the distribution’s release manager manually synchronizes the contents of ros-testing into the main ROS repository. +This is when your packages actually become available to the rest of the ROS community. +To get updates on when the next synchronization (sync) is coming, subscribe to thePackaging and Release Management Category on ROS Discourse. + +Code Examples: + +Language: unknown +sudoaptinstallpython3-bloompython3-catkin-pkg + +Language: unknown +sudodnfinstallpython3-bloompython3-catkin_pkg + +Language: unknown +pip3install-Ubloomcatkin_pkg + +Language: unknown +sudorosdepinit +rosdepupdate + +Language: unknown +{ + "github_user": "", + "oauth_token": "" +} + +Language: unknown +catkin_generate_changelog--all + +Language: unknown +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Changelog for package your_package^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Forthcoming-----------*you can modify this commit message*and this + +Language: unknown +catkin_prepare_release + +Language: unknown +bloom-release--new-track--rosdistrojazzy--trackjazzymy_repo diff --git "a/exported_docs/ros2/Foxy_Fitzroy_(foxy)\357\203\201.txt" "b/exported_docs/ros2/Foxy_Fitzroy_(foxy)\357\203\201.txt" new file mode 100644 index 0000000..37cb980 --- /dev/null +++ "b/exported_docs/ros2/Foxy_Fitzroy_(foxy)\357\203\201.txt" @@ -0,0 +1,90 @@ +Title: Foxy Fitzroy (foxy) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Foxy-Fitzroy.html +Section: Installation +-------------------------------------------------------------------------------- + +Foxy Fitzroy (foxy)Table of ContentsSupported PlatformsInstallationNew features in this ROS 2 releaseChanges in Patch Release 8 (2022-09-28)Launch GroupAction scopes environmentChanges in Patch Release 7 (2022-02-08)Launch set_env frontend behavior changeFix launch frontend parserFix memory leaks and undefined behavior in rmw_fastrtps_dynamic_cppChanges in Patch Release 2 (2020-08-07)Bug in static_transform_publisherChanges since the Eloquent releaseClassic CMake vs. modern CMakeament_export_interfaces replaced by ament_export_targetsrosidl_generator_c|cpp namespace / API changesDefault working directory for ament_add_testDefault Console Logging FormatDefault Console Logging Output Streamlaunch_rosrclcpprclcpp_actionrclpyrmw_connext_cpprvizstd_msgsSecurity featuresKnown IssuesTimeline before the releaseFoxy Fitzroyis the sixth release of ROS 2.Supported PlatformsFoxy Fitzroy is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 20.04 (Focal):amd64andarm64Mac macOS 10.14 (Mojave)Windows 10 (Visual Studio 2019)Tier 3 platforms:Ubuntu 20.04 (Focal):arm32Debian Buster (10):amd64,arm64andarm32OpenEmbedded Thud (2.6) / webOS OSE:arm32andx86For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Foxy FitzroyNew features in this ROS 2 releaseDuring the development theFoxy meta-ticketon GitHub contains an up-to-date state of the ongoing high-level tasks as well as references specific tickets with more details.Changes in Patch Release 8 (2022-09-28)Launch GroupAction scopes environmentTheSetEnvironmentVariableaction is now scoped to anyGroupActionit is returned from.For example, consider the following launch files,PythonXMLimportlaunchfromlaunch.actionsimportSetEnvironmentVariablefromlaunch.actionsimportGroupActionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnlaunch.LaunchDescription([SetEnvironmentVariable(name='my_env_var',value='1'),Node(package='foo',executable='foo',output='screen'),GroupAction([SetEnvironmentVariable(name='my_env_var',value='2'),]),])Before patch release 8, the nodefoowill start withmy_env_var=2, but now it will start withmy_env_var=1.To opt-out of the new behavior, you can set the argumentscoped=Falseon theGroupAction.Related tickets:ros2#1244launch#630Changes in Patch Release 7 (2022-02-08)Launch set_env frontend behavior changelaunch#468inadvertently changed behavior to the scope of theset_envaction in frontend launch files. +Changes to environment variables using theset_envaction are no longer scoped to parentgroupactions, and instead apply globally. +Since it was backported, the change affects this release.We consider this change a regression and intend to fix the behavior in the next patch release and in future ROS distributions. +We also plan to fix the behavior in Python launch files, which have never scoped setting environment variables properly.Related issues:ros2#1244launch#597Fix launch frontend parserA refactor of the launch frontend parser fixed someissues parsing special characters. +As a result, there has been a small behavior change when it comes to parsing strings. +For example, previously to pass a number as a string you would have to add extra quotation marks (two sets of quotation marks were needed if using a substitution):After the refactor, the above will result in the the string"''3''"(note the extra set of quotation marks). +Now, users should use thetypeattribute to signal that the value should be interpreted as a string:Related pull requests:launch#530launch_ros#265Fix memory leaks and undefined behavior in rmw_fastrtps_dynamic_cppAPI was changed in the following header files:rmw_fastrtps_dynamic_cpp/TypeSupport.hpprmw_fastrtps_dynamic_cpp/TypeSupport_impl.hppThough technically they are publically accessible, it is unlikely people are using them directly. +Therefore, we decided to break API in order to fix memory leaks and undefined behavior.The fix was originally submitted inrmw_fastrtps#429and later backported to Foxy inrmw_fastrtps#577.Changes in Patch Release 2 (2020-08-07)Bug in static_transform_publisherDuring the development of Foxy, a bug was introduced into the tf2_ros static_transform_publisher program. +The implementation of the order of the Euler angles passed to static_transform_publisher disagrees with the documentation. +Foxy patch release 2fixesthe order so that the implementation agrees with the documentation (yaw, pitch, roll). +For users who have started using the initial Foxy release or patch release 1, this means that any launch files that use static_transform_publisher will have to have the command-line order swapped according to the new order. +For users who are coming from ROS 2 Dashing, ROS 2 Eloquent, or ROS 1, no changes need to be made to port to Foxy patch release 2.Changes since the Eloquent releaseClassic CMake vs. modern CMakeIn “classic” CMake a package provides CMake variables like_INCLUDE_DIRSand_LIBRARIESwhen beingfind_package()-ed. +Withament_cmakethat is achieved by callingament_export_include_directoriesandament_export_libraries. +In combination withament_export_dependencies,ament_cmakeensures that all include directories and libraries of recursive dependencies are concatenated and included in these variables.In “modern” CMake a package provides an interface target instead (commonly named::) which in itself encapsulates all recursive dependencies. +In order to export a library target to use modern CMakeament_export_targetsneeds to be called with an export name which is also used when installing the libraries usinginstall(TARGETSEXPORT...). +The exported interface targets are available through the CMake variable_TARGETS. +For library targets to be exportable like this they must not rely on classic functions affecting global state likeinclude_directories()but set the include directories on the target itself - for the build as well as install environment - using generator expressions, e.g.target_include_directories(PUBLIC"$""$").Whenament_target_dependenciesis used to add dependencies to a library target the function uses modern CMake targets when they are available. +Otherwise it falls back to using classic CMake variables. +As a consequence you should only export modern CMake targets if all dependencies are also providing modern CMake targets.Otherwise the exported interface target will contain the absolute paths to include directories / libraries in the generated CMake logic which makes the package non-relocatable.For examples how packages have been updated to modern CMake in Foxy seeros2/ros2#904.ament_export_interfaces replaced by ament_export_targetsThe CMake functionament_export_interfacesfrom the packageament_cmake_export_interfaceshas been deprecated in favor of the functionament_export_targetsin the new packageament_cmake_export_targets. +See the GitHub ticketament/ament_cmake#237for more context.rosidl_generator_c|cpp namespace / API changesThe packagesrosidl_generator_candrosidl_generator_cpphave been refactored with many headers and sources moved into the new packagesrosidl_runtime_candrosidl_runtime_cpp. +The intention is to remove run dependencies on the generator packages and therefore the code generation tools using Python. +While moving the headers the include paths / namespaces were updated accordingly so in many cases changing include directives from the generator package to the runtime package is sufficient.The generated C / C++ code has also been refactored. +The files ending in__struct.h|hpp,__functions.h,__traits.hpp, etc. have been moved into a subdirectorydetailbut most code only includes the header named after the interface without any of these suffixes.Some types regarding string and sequence bounds have also been renamed to match the naming conventions but they aren’t expected to be used in user code (above RMW implementation and type support packages)For more information seeros2/rosidl#446 (for C)andros2/rosidl#447 (for C++).Default working directory for ament_add_testThe default working directory for tests added withament_add_testhas been changed toCMAKE_CURRENT_BINARY_DIRto match the behavior of CMakeadd_test. +Either update the tests to work with the new default or passWORKING_DIRECTORY${CMAKE_SOURCE_DIR}to restore the previous value.Default Console Logging FormatThe default console logging output format was changed to include the timestamp by default, see:https://github.com/ros2/rcutils/pull/190https://discourse.ros.org/t/ros2-logging-format/11549Default Console Logging Output StreamAs of Foxy, all logging messages at all severity levels get logged to stderr by default. +This ensures that logging messages come out immediately, and brings the ROS 2 logging system into alignment with most other logging systems. +It is possible to change the stream to stdout at runtime via the RCUTILS_LOGGING_USE_STDOUT environment variable, but all logging messages will still go to the same stream. +Seehttps://github.com/ros2/rcutils/pull/196for more details.launch_rosNode name and namespace parameters changedTheNodeaction parameters related to naming have been changed:node_namehas been renamed tonamenode_namespacehas been renamed tonamespacenode_executablehas been renamed toexecutableexec_namehas been added for naming the process associated with the node. +Previously, users would have used thenamekeyword argument.The old parameters have been deprecated.These changes were made to make the launch frontend more idiomatic. +For example, instead ofwe can now writeThis change also applies toComposableNodeContainer,ComposableNode, andLifecycleNode. +For examples, see therelevant changes to the demos.Related pull request in launch_ros.rclcppChange in Advanced Subscription Callback SignatureWith the pull requesthttps://github.com/ros2/rclcpp/pull/1047the signature of callbacks which receive the message info with the message has changed. +Previously it used thermwtypermw_message_info_t, but now uses therclcpptyperclcpp::MessageInfo. +The required changes are straightforward, and can be seen demonstrated in these pull requests:https://github.com/ros2/system_tests/pull/423/fileshttps://github.com/ros2/rosbag2/pull/375/fileshttps://github.com/ros2/ros1_bridge/pull/253/filesChange in Serialized Message Callback SignatureThe pull requestros2/rclcpp#1081introduces a new signature of the callbacks for retrieving ROS messages in serialized form. +The previously used C-Structrcl_serialized_message_tis being superseded by a C++ data typerclcpp::SerializedMessage.The example nodes indemo_nodes_cpp, namelytalker_serialized_messageas well aslistener_serialized_messagereflect these changes.Breaking change in Node Interface getters’ signatureWith pull requestros2/rclcpp#1069, the signature of node interface getters has been modified to return shared ownership of node interfaces (i.e. anstd::shared_ptr) instead of a non-owning raw pointer. +Required changes in downstream packages that relied on the previous signature are simple and straightforward: use thestd::shared_ptr::get()method.Deprecate set_on_parameters_set_callbackInstead, use therclcpp::Nodemethodsadd_on_set_parameters_callbackandremove_on_set_parameters_callbackfor adding and removing functions that are called when parameters are set.Related pull request:https://github.com/ros2/rclcpp/pull/1123Breaking change in Publisher getter signatureWith pull requestros2/rclcpp#1119, the signature of publisher handle getter has been modified to return shared ownership of the underlying rcl structure (i.e. anstd::shared_ptr) instead of a non-owning raw pointer. +This was necessary to fix a segfault in certain circumstances. +Required changes in downstream packages that relied on the previous signature are simple and straightforward: use thestd::shared_ptr::get()method.rclcpp_actionDeprecate ClientGoalHandle::async_result()Using this API, it is possible to run into a race condition causing an exception to be thrown. +Instead, prefer to useClient::async_get_result(), which is safer.Seeros2/rclcpp#1120and the connected issue for more info.rclpySupport for multiple on parameter set callbacksUse theNodemethodsadd_on_set_parameters_callbackandremove_on_set_parameters_callbackfor adding and removing functions that are called when parameters are set.The methodset_parameters_callbackhas been deprecated.Related pull requests:https://github.com/ros2/rclpy/pull/457,https://github.com/ros2/rclpy/pull/504rmw_connext_cppConnext 5.1 locator kinds compatibility modeUp to and includingEloquent,rmw_connext_cppwas settingdds.transport.use_510_compatible_locator_kindsproperty totrue. +This property is not being forced anymore, and shared transport communication betweenFoxyand previous releases will stop working. +Logs similar to:PRESParticipant_checkTransportInfoMatching:Warning:discoveredremoteparticipant'RTI Administration Console'usingthe'shmem'transportwithclassID16777216. +ThisclassIDdoesnotmatchtheclassID2ofthesametransportinthelocalparticipant'talker'. +Thesetwoparticipantswillnotcommunicateoverthe'shmem'transport. +Checkthevalueoftheproperty'dds.transport.use_510_compatible_locator_kinds'inthelocalparticipant. +Seehttps://community.rti.com/kb/what-causes-error-discovered-remote-participantforadditionalinfo.will be observed when this incompatibility happens.If compatibility is needed, it can be set up in an external QoS profiles files containing:dds.transport.use_510_compatible_locator_kinds1Remember to set theNDDS_QOS_PROFILESenvironment variable to the QoS profiles file path. +For more information, seeHowtoChangeTransportSettingsin5.2.0ApplicationsforCompatibilitywith5.1.0section ofTransport_Compatibility.rvizTools timestamp messages using ROS time‘2D Pose Estimate’, ‘2D Nav Goal’, and ‘Publish Point’ tools now timestamp their messages using ROS time instead of system time, in order for theuse_sim_timeparameter to have an effect on them.Related pull request:https://github.com/ros2/rviz/pull/519std_msgsDeprecation of messagesAlthough discouraged for a long time we have officially deprecated the following messages instd_msgs. +There are copies inexample_interfacesstd_msgs/msg/Boolstd_msgs/msg/Bytestd_msgs/msg/ByteMultiArraystd_msgs/msg/Charstd_msgs/msg/Float32std_msgs/msg/Float32MultiArraystd_msgs/msg/Float64std_msgs/msg/Float64MultiArraystd_msgs/msg/Int16std_msgs/msg/Int16MultiArraystd_msgs/msg/Int32std_msgs/msg/Int32MultiArraystd_msgs/msg/Int64std_msgs/msg/Int64MultiArraystd_msgs/msg/Int8std_msgs/msg/Int8MultiArraystd_msgs/msg/MultiArrayDimensionstd_msgs/msg/MultiArrayLayoutstd_msgs/msg/Stringstd_msgs/msg/UInt16std_msgs/msg/UInt16MultiArraystd_msgs/msg/UInt32std_msgs/msg/UInt32MultiArraystd_msgs/msg/UInt64std_msgs/msg/UInt64MultiArraystd_msgs/msg/UInt8std_msgs/msg/UInt8MultiArraySecurity featuresUse of security enclavesAs of Foxy, domain participants are no longer mapped directly to ROS nodes. +As a result, ROS 2 security features (which are specific to domain participants) are also no longer mapped directly to ROS nodes. +Instead, Foxy introduces the concept of a security “enclave”, where an “enclave” is a process or group of processes that will share the same identity and access control rules.This means that security artifacts arenotretrieved based on the node name anymore but based on the Security enclave name. +A node enclave name can be set by using the ROS argument--enclave, e.g.ros2rundemo_nodes_pytalker--ros-args--enclave/my_enclaveRelated design document:https://github.com/ros2/design/pull/274Note that permissions files are limited by the underlying transport packet size, so grouping many permissions under the same enclave willnotwork if the resulting permissions file exceed 64kB. +Related issue[ros2/sros2#228]Renaming of the environment variablesEnvironment variables renamingName in EloquentName in FoxyROS_SECURITY_ROOT_DIRECTORYROS_SECURITY_KEYSTOREROS_SECURITY_NODE_DIRECTORYROS_SECURITY_ENCLAVE_OVERRIDEKnown Issues[ros2/ros2#922]Services’ performance is flaky forrclcppnodes using eProsima Fast-RTPS or ADLINK CycloneDDS as RMW implementation. +Specifically, service clients sometimes do not receive the response from servers.[ros2/rclcpp#1212]Ready reentrant Waitable objects can attempt to execute multiple times.Timeline before the releaseA few milestones leading up to the release:NoteThe dates below reflect an extension by roughly two weeks due to the coronavirus pandemic.Wed. April 22nd, 2020API and feature freeze forros_core[1]packages. +Note that this includesrmw, which is a recursive dependency ofros_core. +Only bug fix releases should be made after this point. +New packages can be released independently.Mon. April 29th, 2020 (beta)Updated releases ofdesktop[2]packages available. +Testing of the new features.Wed. May 27th, 2020 (release candidate)Updated releases ofdesktop[2]packages available.Wed. June 3rd, 2020Freeze rosdistro. +No PRs for Foxy on therosdistrorepo will be merged (reopens after the release announcement).[1]Theros_corevariant described in thevariantsrepository.[2](1,2)Thedesktopvariant described in thevariantsrepository. + +Code Examples: + +Language: unknown +importlaunchfromlaunch.actionsimportSetEnvironmentVariablefromlaunch.actionsimportGroupActionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnlaunch.LaunchDescription([SetEnvironmentVariable(name='my_env_var',value='1'),Node(package='foo',executable='foo',output='screen'),GroupAction([SetEnvironmentVariable(name='my_env_var',value='2'),]),]) + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown +PRESParticipant_checkTransportInfoMatching:Warning:discoveredremoteparticipant'RTI Administration Console'usingthe'shmem'transportwithclassID16777216. +ThisclassIDdoesnotmatchtheclassID2ofthesametransportinthelocalparticipant'talker'. +Thesetwoparticipantswillnotcommunicateoverthe'shmem'transport. +Checkthevalueoftheproperty'dds.transport.use_510_compatible_locator_kinds'inthelocalparticipant. +Seehttps://community.rti.com/kb/what-causes-error-discovered-remote-participantforadditionalinfo. + +Language: unknown +dds.transport.use_510_compatible_locator_kinds1 diff --git "a/exported_docs/ros2/Galactic_Geochelone_(galactic)\357\203\201.txt" "b/exported_docs/ros2/Galactic_Geochelone_(galactic)\357\203\201.txt" new file mode 100644 index 0000000..5e6fd56 --- /dev/null +++ "b/exported_docs/ros2/Galactic_Geochelone_(galactic)\357\203\201.txt" @@ -0,0 +1,250 @@ +Title: Galactic Geochelone (galactic) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Galactic-Geochelone.html +Section: Installation +-------------------------------------------------------------------------------- + +Galactic Geochelone (galactic)Table of ContentsSupported PlatformsInstallationNew features in this ROS 2 releaseAbility to specify per-logger log levelsAbility to configure logging directory through environment variablesAbility to invokerosidlpipeline outside CMakeExternally configure QoS at start-upPython point_cloud2 utilities availableRViz2 Time Panelros2 topic echo can print serialized dataGet the YAML representation of messagesAbility to load parameter files at runtime through the ros2 commandTools to check for QoS incompatibilitiesUse launch substitutions in parameter filesSupport for unique network flowsRosbag2 New FeaturesChanges since the Foxy releaseDefault RMW changed to Eclipse Cyclone DDSConnext RMW changed to rmw_connextddsLarge improvements in testing and overall qualityrmwament_cmakenav2tf2_ros Python split out of tf2_rostf2_ros Python TransformListener uses global namespacerclcpprclpyrclcpp_actionrosidl_typesupport_introspection_crcl_lifecycle and rclcpp_lifecyclercl_lifecycle and rclcpp_lifecycleKnown Issuesros2clirqtrviz2Timeline before the releaseGalactic Geocheloneis the seventh release of ROS 2. +What follows is highlights of the important changes and features in Galactic Geochelone since the last release. +For a list of all of the changes since Foxy, see thelong form changelog.Supported PlatformsGalactic Geochelone is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 20.04 (Focal):amd64andarm64Windows 10 (Visual Studio 2019):amd64Tier 2 platforms:RHEL 8:amd64Tier 3 platforms:Ubuntu 20.04 (Focal):arm32Debian Bullseye (11):amd64,arm64andarm32OpenEmbedded Thud (2.6) / webOS OSE:arm32andarm64Mac macOS 10.14 (Mojave):amd64For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Galactic GeocheloneNew features in this ROS 2 releaseAbility to specify per-logger log levelsIt is now possible to specify different logging levels for different loggers on the command line:ros2rundemo_nodes_cpptalker--ros-args--log-levelWARN--log-leveltalker:=DEBUGThe above command sets a global log level of WARN, but sets the log level of the talker node messages to DEBUG. +The--log-levelcommand-line option can be passed an arbitrary number of times to set different log levels for each logger.Ability to configure logging directory through environment variablesIt is now possible to configure the logging directory through two environment variables:ROS_LOG_DIRandROS_HOME. +The logic is as follows:Use$ROS_LOG_DIRifROS_LOG_DIRis set and not empty.Otherwise, use$ROS_HOME/log, using~/.rosforROS_HOMEif not set or if empty.Thus the default value stays the same:~/.ros/log.Related PRs:ros2/rcl_logging#53andros2/launch#460.For example:ROS_LOG_DIR=/tmp/fooros2rundemo_nodes_cpptalkerWill place all logs in/tmp/foo.ROS_HOME=/path/to/homeros2rundemo_nodes_cpptalkerWill place all logs in/path/to/home/log.Ability to invokerosidlpipeline outside CMakeIt is now straightforward to invoke therosidlinterface generation pipeline outside CMake. +Source code generators and interface definition translators are accessible through a unified command line interface.For example, given aDemomessage in somedemopackage like:mkdir-pdemo/msgcddemo +cat<< EOF > msg/Demo.msgstd_msgs/Header headergeometry_msgs/Twist twistgeometry_msgs/Accel accelEOFit is easy to generate C, C++, and Python support source code:rosidlgenerate-ogen-tc-tcpp-tpy-I$(ros2pkgprefix--sharestd_msgs)/..\-I$(ros2pkgprefix--sharegeometry_msgs)/..demomsg/Demo.msgGenerated source code will be put in thegendirectory.One may also translate the message definition to a different format for a third-party code generation tool to consume:rosidltranslate-ogen--toidl-I$(ros2pkgprefix--sharestd_msgs)/..\-I$(ros2pkgprefix--sharegeometry_msgs)/..demomsg/Demo.msgThe translated message definition will be put in thegendirectory.Note that these tools generate sources but do not build it – that responsibility is still on the caller. +This is a first step towards enablingrosidlinterface generation in build systems other than CMake. +See thedesign documentfor further reference and next steps.Externally configure QoS at start-upIt is now possible to externally configure the QoS settings for a node at start-up time. +QoS settings arenotconfigurable during runtime; they are only configurable at start-up. +Node authors must opt-in to enable changing QoS settings at start-up. +If the feature is enabled on a node, then QoS settings can be set with ROS parameters when a node first starts.Demos in C++ and Python can be found here.See thedesign document for more details.Note, user code handling parameter changes with registered callbacks should avoid rejecting updates for unknown parameters. +It was considered bad practice prior to Galactic, but with externally configurable QoS enabled it will result in a hard failure.Related PRs:ros2/rclcpp#1408andros2/rclpy#635Python point_cloud2 utilities availableSeveral utilities for interacting withPointCloud2 messagesin Python wereported to ROS 2. +These utilities allow one to get a list of points from a PointCloud2 message (read_pointsandread_points_list), and to create a PointCloud2 message from a list of points (create_cloudandcreate_cloud_xyz32).An example of creating PointCloud 2 message, then reading it back:importsensor_msgs_py.point_cloud2fromstd_msgs.msgimportHeaderpointlist=[[0.0,0.1,0.2]]pointcloud=sensor_msgs_py.point_cloud2.create_cloud_xyz32(Header(frame_id='frame'),pointlist)forpointinsensor_msgs_py.point_cloud2.read_points(pointcloud):print(point)RViz2 Time PanelThe Rviz2 Time Panel, which shows the current Wall and ROS time, along with the elapsed Wall and ROS time, has beenported to RViz2. +To enable the Time Panel, click on Panels -> Add New Panel, and select “Time”. +A panel that looks like the following will appear:ros2 topic echo can print serialized dataWhen debugging middleware issues, it can be useful to see the raw serialized data that the RMW is sending. +The–raw command-line flagwas added toros2topicechoto show this data. +To see this in action, run the following commands.Terminal 1:$ros2topicpub/chatterstd_msgs/msg/String"data: 'hello'"Terminal 2:$ros2topicecho--raw/chatter +b'\x00\x01\x00\x00\x06\x00\x00\x00hello\x00\x00\x00'---Get the YAML representation of messagesIt is now possible to get a YAML representation of all messages in C++ using theto_yamlfunction. +An example of code that prints out the YAML representation:#include#includeintmain(){std_msgs::msg::Stringmsg;msg.data="hello world";printf("%s",rosidl_generator_traits::to_yaml(msg).c_str());return0;}Ability to load parameter files at runtime through the ros2 commandROS 2 has long had the ability to specify parameter values at startup (through command-line arguments or a YAML file), and to dump current parameters out to a file (throughros2paramdump). +Galactic adds the ability toload parameter values at runtimefrom a YAML file using theros2paramloadverb. +For example:Terminal 1:$ros2rundemo_nodes_cppparameter_blackboardTerminal 2:$ros2paramset/parameter_blackboardfoobar# sets 'foo' parameter to value 'bar'$ros2paramdump/parameter_blackboard# dumps current value of parameters to ./parameter_blackboard.yaml$ros2paramset/parameter_blackboardfoodifferent# sets 'foo' parameter to value 'different'$ros2paramload/parameter_blackboard./parameter_blackboard.yaml# reloads previous state of parameters, 'foo' is back to 'bar'Tools to check for QoS incompatibilitiesBuilt on top of new QoS compatibility check APIs,ros2doctorandrqt_graphcan now detect and report QoS incompatibilities between publishers and subscriptions.Given a publisher and a subscription withincompatible QoS settings:Terminal 1:$ros2rundemo_nodes_pytalker_qos-n1000# i.e. best_effort publisherTerminal 2:$ros2rundemo_nodes_pylistener_qos--reliable-n1000# i.e. reliable subscriptionros2doctorreports:$ros2doctor--report# ...QOSCOMPATIBILITYLIST +topic[type]:/chatter[std_msgs/msg/String]publishernode:talker_qos +subscribernode:listener_qos +compatibilitystatus:ERROR:Besteffortpublisherandreliablesubscription;# ...whilerqt_graphshows:Related PRs:ros2/ros2cli#621,ros-visualization/rqt_graph#61Use launch substitutions in parameter filesJust likerosparamtags in ROS 1roslaunch,launch_roscan now evaluate substitutions in parameter files.For example, given someparameter_file_with_substitutions.yamllike the following:/**:ros__parameters:launch_date:$(command date)Setallow_subststoTrueto get substitutions evaluated uponNodelaunch:importlaunchimportlaunch_ros.parameter_descriptionsimportlaunch_ros.actionsdefgenerate_launch_description():returnlaunch.LaunchDescription([launch_ros.actions.Node(package='demo_nodes_cpp',executable='parameter_blackboard',parameters=[launch_ros.parameter_descriptions.ParameterFile(param_file='parameter_file_with_substitutions.yaml',allow_substs=True)])])XML launch files also support this.Related PR:ros2/launch_ros#168Support for unique network flowsApplications may now require UDP/TCP and IP-based RMW implementations to provide uniquenetwork flows(i.e. uniqueDifferentiated Services Code Pointsand/or uniqueIPv6 Flow Labelsand/or unique ports in IP packet headers) for publishers and subscriptions, enabling QoS specifications for these IP streams in network architectures that support such a feature, like 5G networks.To see this in action, you may run these C++ examples (to be found in theros2/examplesrepository):Terminal 1:ros2runexamples_rclcpp_minimal_publisherpublisher_member_function_with_unique_network_flow_endpointsTerminal 2:ros2runexamples_rclcpp_minimal_subscribersubscriber_member_function_with_unique_network_flow_endpointsSee theUnique Network Flows design documentfor further reference.Rosbag2 New FeaturesSplit recording by timeIn Foxy, you could only split bags as they were recording by the size of the bag, now you can also split by the elapsed time. +The following command will split bagfiles into 100-second chunks.ros2bagrecord--all--max-bag-duration100ros2 bag listThis new command lists installed plugins of various types that rosbag2 uses.$ros2bagliststorage +rosbag2_v2 +sqlite3 + +$ros2baglistconverter +rosbag_v2_converterCompression implementation is a pluginIn Foxy, rosbag2 compression was hardcoded with a Zstd library implementation. +This has been rearchitected so that compression implementations are a plugin, and can be swapped out without modifying the core rosbag2 codebase. +The default plugin that ships withros-galactic-rosbag2is still the Zstd plugin - but now more can be released and used, and by selectively installing packages Zstd could be excluded from an installation.Compress per-messageIn Foxy, you could automatically compress each rosbag file as it was split (per-file compression), but now you can also specify per-message compression.ros2bagrecord--all--compression-formatzstd--compression-modemessageRosbag2 Python APIA new packagerosbag2_pyhas been released in Galactic, which provides a Python API. +This package is apybind11binding around the C++ API. +As of the initial Galactic release, it does not yet expose all functionality available via therosbag2_cppAPI, but it is the sole connection for theros2bagCLI tool, so a good deal of functionality is available.performance testing package and performance improvementsA thorough performance analysis project was performed on rosbag2 since the Foxy release. +The full initial report is available athttps://github.com/ros2/rosbag2/blob/galactic/rosbag2_performance/rosbag2_performance_benchmarking/docs/rosbag2_performance_improvements.pdf. +The packagerosbag2_performance_benchmarkingprovides tools to run performance analyses, especially on recording, which helps us maintain and improve the performance of rosbag2.Following this report, key work was done do improve the performance to a much more usable state for actual robot workflows. +To highlight a key metric - in a high bandwidth stress test (200Mbps), the Foxy release dropped up to 70% of messages, whereas the Galactic version was approximately 100% retention. +Please see the linked report for more details.--regexand--excludeoptions for topic selectionThe new recording options--regexand--excludeallow for fine-tuning the topics recorded in a bag, without having to explicitly list all topics. +These options may be used together or separately, and in conjunction with--allThe following command will record only topics with “scan” in the name.ros2bagrecord--regex"*scan*"The following command will record all topics except for ones in/my_namespace/ros2bagrecord--all--exclude"/my_namespace/*"ros2bagreindexROS 2 bags are represented by a directory, instead of a single file. +This directory contains ametadata.yamlfile, and one or more bag files. +When themetadata.yamlfile is lost or missing,ros2bagreindex$bag_dirwill attempt to reconstruct it by reading all the bag files in the directory.Playback time controlNew controls have been added for rosbag2 playback - pause & resume, change rate, and play-next. +As of the Galactic release, these controls are exposed only as services on the rosbag2 player node. +Development is in progress to expose them to keyboard controls as well inros2bagplay, but until then a user application with buttons or keyboard controls may be trivially implemented to call these services.# In one shell$ros2bagplaymy_bag# In another shell$ros2servicelist-t +/rosbag2_player/get_rate[rosbag2_interfaces/srv/GetRate]/rosbag2_player/is_paused[rosbag2_interfaces/srv/IsPaused]/rosbag2_player/pause[rosbag2_interfaces/srv/Pause]/rosbag2_player/play_next[rosbag2_interfaces/srv/PlayNext]/rosbag2_player/resume[rosbag2_interfaces/srv/Resume]/rosbag2_player/set_rate[rosbag2_interfaces/srv/SetRate]/rosbag2_player/toggle_paused[rosbag2_interfaces/srv/TogglePaused]# Check if playback is paused$ros2servicecall/rosbag2_player/is_pausedrosbag2_interfaces/IsPaused# Pause playback$ros2servicecall/rosbag2_player/pauserosbag2_interfaces/Pause# Resume playback$ros2servicecall/rosbag2_player/resumerosbag2_interfaces/Resume# Change the paused state of playback to its opposite. If playing, pauses. If paused, resumes.$ros2servicecall/rosbag2_player/toggle_pausedrosbag2_interfaces/TogglePaused# Get the current playback rate$ros2servicecall/rosbag2_player/get_rate# Set the current playback rate (must be > 0)$ros2servicecall/rosbag2_player/set_raterosbag2_interfaces/SetRate"rate: 0.1"# Play a single next message (only works while paused)$ros2servicecall/rosbag2_player/play_nextrosbag2_interfaces/PlayNextPlayback publishes /clockRosbag2 can also dictate “simulation time” by publishing to the/clocktopic during playback. +The following commands will publish the clock message at a regular interval.# Publish at default rate - 40Hzros2bagplaymy_bag--clock# Publish at specific rate - 100Hzros2bagplaymy_bag--clock100Changes since the Foxy releaseDefault RMW changed to Eclipse Cyclone DDSDuring the Galactic development process, the ROS 2 Technical Steering Committeevotedto change the default ROS middleware (RMW) toEclipse Cyclone DDSproject ofEclipse Foundation. +Without any configuration changes, users will get Eclipse Cyclone DDS by default. +Fast DDS and Connext are still Tier-1 supported RMW vendors, and users can opt-in to use one of these RMWs at their discretion by using theRMW_IMPLEMENTATIONenvironment variable. +See theWorking with multiple RMW implementations guidefor more information.Connext RMW changed to rmw_connextddsA new RMW for Connext calledrmw_connextddswas merged for Galactic. +This RMW has better performance and fixes many of the issues with the older RMWrmw_connext_cpp.Large improvements in testing and overall qualityGalactic contains many changes that fix race conditions, plug memory leaks, and fix user reported problems. +Besides these changes, there was a concerted effort during Galactic development to improve overall quality of the system by implementingREP 2004. +Therclcpppackage and all of its dependencies (which include most of the ROS 2 non-Python core packages) were brought up toQuality Level 1by:Having a version policy (QL1 requirement 1)Having a documented change control process (QL1 requirement 2)Documenting all features and public APIs (QL1 requirement 3)Adding many additional tests (QL1 requirement 4):System tests for all featuresUnit tests for all public APIsNightly performance testsCode coverage at 95%Having all runtime dependencies of packages be at least as high as the package (QL1 requirement 5)Supporting all of the REP-2000 platforms (QL1 requirement 6)Having a vulnerability disclosure policy (QL1 requirement 7)rmwNew API for checking QoS profile compatibilityrmw_qos_profile_check_compatibleis a new function for checking the compatibility of two QoS profiles.RMW vendors should implement this API for QoS debugging and introspection features in tools such asrqt_graphto work correctly.Related PR:ros2/rmw#299ament_cmakeament_install_python_package()now installs a Python eggBy installing a flat Python egg, Python packages installed usingament_install_python_package()can be discovered using modules such aspkg_resourcesand`importlib.metadata. Also, additional metadata can be provided in asetup.cfgfile (including entry points).Related PR:ament/ament_cmake#326ament_target_dependencies()handles SYSTEM dependenciesSome package dependencies can now be marked as SYSTEM dependencies, helping to cope with warnings in external code. Typically, SYSTEM dependencies are also excluded from dependency calculations – use them with care.Related PR:ament/ament_cmake#297nav2Changes include, but are not limited to, a number of stability improvements, new plugins, interface changes, costmap filters. +SeeMigration Guidesfor full listtf2_ros Python split out of tf2_rosThe Python code that used to live in tf2_ros has been moved into its own package named tf2_ros_py. +Any existing Python code that depends on tf2_ros will continue to work, but the package.xml of those packages should be amended toexec_dependon tf2_ros_py.tf2_ros Python TransformListener uses global namespaceThe PythonTransformListenernow subscribes to/tfand/tf_staticin the global namespace. +Previously, it was susbcribing in the node’s namespace. +This means that the node’s namespace will no longer have an effect on the/tfand/tf_staticsubscriptions.For example:ros2runtf2_rostf2_echo--ros-args-r__ns:=/test--odombase_linkwill subscribe to/tfand/tf_static, asros2topiclistwill show.Related PR:ros2/geometry2#390rclcppChange in spin_until_future_complete template parametersThe first template parameter ofExecutor::spin_until_future_completewas the future result typeResultT, and the method only accepted astd::shared_future. +In order to accept other types of futures (e.g.:std::future), that parameter was changed to the future type itself.In places where aspin_until_future_completecall was relying on template argument deduction, no change is needed. +If not, this is an example diff:std::shared_future future; +...-executor.spin_until_future_complete(future);+executor.spin_until_future_complete>(future);For more details, seeros2/rclcpp#1160. +For an example of the needed changes in user code, seeros-visualization/interactive_markers#72.Change in default/clocksubscription QoS profileThe default was changed from a reliable communication with history depth 10 to a best effort communication with history depth 1. +Seeros2/rclcpp#1312.Waitable APIWaitable API was modified to avoid issues with theMultiThreadedExecutor. +This only affects users implementing a custom waitable. +Seeros2/rclcpp#1241for more details.Change inrclcpp’s logging macrosPreviously, the logging macros were vulnerable to aformat string attack, where the format string is evaluated and can potentially execute code, read the stack, or cause a segmentation fault in the running program. +To address this security issue, the logging macro now accepts only string literals for it’s format string argument.If you previously had code like:constchar*my_const_char_stringformat="Foo";RCLCPP_DEBUG(get_logger(),my_const_char_string);you should now replace it with:constchar*my_const_char_stringformat="Foo";RCLCPP_DEBUG(get_logger(),"%s",my_const_char_string);or:RCLCPP_DEBUG(get_logger(),"Foo");This change removes some convenience from the logging macros, asstd::strings are no longer accepted as the format argument.If you previously had code with no format arguments like:std::stringmy_std_string="Foo";RCLCPP_DEBUG(get_logger(),my_std_string);you should now replace it with:std::stringmy_std_string="Foo";RCLCPP_DEBUG(get_logger(),"%s",my_std_string.c_str());NoteIf you are using astd::stringas a format string with format arguments, converting that string to achar*and using it as the format string will yield a format security warning. That’s because the compiler has no way at compile to introspect into thestd::stringto verify the arguments. To avoid the security warning, we recommend you build the string manually and pass it in with no format arguments like the previous example.std::stringstreamtypes are still accepted as arguments to the stream logging macros. +Seeros2/rclcpp#1442for more details.Parameter types are now static by defaultPreviously, the type of a parameter could be changed when a parameter was set. +For example, if a parameter was declared as an integer, a later call to set the parameter could change that type to a string. +This behavior could lead to bugs, and is rarely what the user wants. +As of Galactic parameter types are static by default, and attempts to change the type will fail. +If the previous dynamic behavior is desired, there is an mechanism to opt it in (see the code below).// declare integer parameter with default value, trying to set it to a different type will fail.node->declare_parameter("my_int",5);// declare string parameter with no default and mandatory user provided override.// i.e. the user must pass a parameter file setting it or a command line rule -p :=node->declare_parameter("string_mandatory_override",rclcpp::PARAMETER_STRING);// Conditionally declare a floating point parameter with a mandatory override.// Useful when the parameter is only needed depending on other conditions and no default is reasonable.if(mode=="modeA"){node->declare_parameter("conditionally_declare_double_parameter",rclcpp::PARAMETER_DOUBLE);}// You can also get the old dynamic typing behavior if you want:rcl_interfaces::msg::ParameterDescriptordescriptor;descriptor.dynamic_typing=true;node->declare_parameter("dynamically_typed_param",rclcpp::ParameterValue{},descriptor);For more details seehttps://github.com/ros2/rclcpp/blob/galactic/rclcpp/doc/notes_on_statically_typed_parameters.md.New API for checking QoS profile compatibilityqos_check_compatibleis a new function for checking the compatibility of two QoS profiles.Related PR:ros2/rclcpp#1554rclpyRemoval of deprecated Node.set_parameters_callbackThe methodNode.set_parameters_callbackwasdeprecated in ROS Foxyand has beenremoved in ROS Galactic. +UseNode.add_on_set_parameters_callback()instead. +Here is some example code using it.importrclpyimportrclpy.nodefromrcl_interfaces.msgimportParameterTypefromrcl_interfaces.msgimportSetParametersResultrclpy.init()node=rclpy.node.Node('callback_example')node.declare_parameter('my_param','initial value')defon_parameter_event(parameter_list):forparameterinparameter_list:node.get_logger().info(f'Got{parameter.name}={parameter.value}')returnSetParametersResult(successful=True)node.add_on_set_parameters_callback(on_parameter_event)rclpy.spin(node)Run this command to see the parameter callback in action.ros2paramset/callback_examplemy_param"Hello World"Parameter types are now static by defaultIn Foxy and earlier a call to set a parameter could change its type. +As of Galactic parameter types are static and cannot be changed by default. +If the previous behavior is desired, then setdynamic_typingto true in the parameter descriptor. +Here is an example.importrclpyimportrclpy.nodefromrcl_interfaces.msgimportParameterDescriptorrclpy.init()node=rclpy.node.Node('static_param_example')node.declare_parameter('static_param','initial value')node.declare_parameter('dynamic_param','initial value',descriptor=ParameterDescriptor(dynamic_typing=True))rclpy.spin(node)Run these commands to see how statically and dynamically typed parameters are different.$ros2paramset/static_param_exampledynamic_param42Set parameter successful$ros2paramset/static_param_examplestatic_param42Setting parameter failed: Wrong parameter type, expected 'Type.STRING' got 'Type.INTEGER'For more details seehttps://github.com/ros2/rclcpp/blob/galactic/rclcpp/doc/notes_on_statically_typed_parameters.md.New API for checking QoS profile compatibilityrclpy.qos.qos_check_compatibleisa new functionfor checking the compatibility of two QoS profiles. +If the profiles are compatible, then a publisher and subscriber using them will be able to talk to each other.importrclpy.qospublisher_profile=rclpy.qos.qos_profile_sensor_datasubscription_profile=rclpy.qos.qos_profile_parameter_eventsprint(rclpy.qos.qos_check_compatible(publisher_profile,subscription_profile))$python3qos_check_compatible_example.py(QoSCompatibility.ERROR, 'ERROR: Best effort publisher and reliable subscription;')rclcpp_actionAction client goal response callback signature changedThe goal response callback should now take a shared pointer to a goal handle, instead of a future.Forexample, old signature:voidgoal_response_callback(std::shared_futurefuture)New signature:voidgoal_response_callback(GoalHandleFibonacci::SharedPtrgoal_handle)Related PR:ros2/rclcpp#1311rosidl_typesupport_introspection_cAPI break in function that gets an element from an arrayThe signature of the function was changed because it was semantically different to all the other functions used to get an element from an array or sequence. +This only affects authors of rmw implementations using the introspection typesupport.For further details, seeros2/rosidl#531.rcl_lifecycle and rclcpp_lifecycleRCL’s lifecycle state machine gets new init APIThe lifecycle state machine in rcl_lifecycle was modified to expect a newly introduced options struct, combining general configurations for the state machine. +The option struct allows to indicate whether the state machine shall be initialized with default values, whether its attached services are active and which allocator to be used.rcl_ret_trcl_lifecycle_state_machine_init(rcl_lifecycle_state_machine_t*state_machine,rcl_node_t*node_handle,constrosidl_message_type_support_t*ts_pub_notify,constrosidl_service_type_support_t*ts_srv_change_state,constrosidl_service_type_support_t*ts_srv_get_state,constrosidl_service_type_support_t*ts_srv_get_available_states,constrosidl_service_type_support_t*ts_srv_get_available_transitions,constrosidl_service_type_support_t*ts_srv_get_transition_graph,constrcl_lifecycle_state_machine_options_t*state_machine_options);RCL’s lifecycle state machine stores allocator instanceThe options struct (discussed above) entails an instance of the allocator being used for initializing the state machine. +This options struct and there the embodied allocator are being stored within the lifecycle state machine. +As a direct consequence, thercl_lifecycle_finifunctionno longer expects an allocator in its fini function but rather uses the allocator set in the options struct for deallocating its internal data structures.rcl_ret_trcl_lifecycle_state_machine_fini(rcl_lifecycle_state_machine_t*state_machine,rcl_node_t*node_handle);RCLCPP’s lifecycle node exposes option to not instantiate servicesIn order to use rclcpp’s lifecycle nodes without exposing its internal services such aschange_state,get_stateet. al., the constructor of a lifecycle node has a newly introduced parameter indicating whether or not the services shall be available. +This boolean flag is set to true by default, not requiring any changes to existing API if not wished.explicitLifecycleNode(conststd::string&node_name,constrclcpp::NodeOptions&options=rclcpp::NodeOptions(),boolenable_communication_interface=true);Related PRs:ros2/rcl#882andros2/rclcpp#1507rcl_lifecycle and rclcpp_lifecycleRecording - Split by timeKnown Issuesros2cliDaemon slows down CLI on WindowsAs a workaround, CLI commands may be used without a daemon e.g.:ros2topiclist--no-daemonIssue is tracked byros2/ros2cli#637.rqtSome rqt_bag icons are missingThe icons to “Zoom In”, “Zoom Out”, “Zoom Home”, and “Toggle Thumbnails” are missing inrqt_bag. +The issue is tracked inros-visualization/rqt_bag#102Most rqt utilities don’t work standalone on WindowsLaunching the rqt utilities “standalone” on Windows (likeros2runrqt_graphrqt_graph) generally doesn’t work. +The workaround is to launch the rqt container process (rqt), and then insert the plugins to be used.rviz2RViz2 panel close buttons are blankThe upper right-hand corner of every RViz2 panel should contain an “X” to allow one to close the panel. +Those buttons are there, but the “X” inside of them is missing on all platforms. +The issue is being tracked inros2/rviz2#692.Timeline before the releaseMon. March 22, 2021 - AlphaPreliminary testing and stabilization of ROS Core[1]packages.Mon. April 5, 2021 - FreezeAPI and feature freeze for ROS Core[1]packages in Rolling Ridley. +Note that this includesrmw, which is a recursive dependency ofros_core. +Only bug fix releases should be made after this point. +New packages can be released independently.Mon. April 19, 2021 - BranchBranch from Rolling Ridley.rosdistrois reopened for Rolling PRs for ROS Core[1]packages. +Galactic development shifts fromros-rolling-*packages toros-galactic-*packages.Mon. April 26, 2021 - BetaUpdated releases of ROS Desktop[2]packages available. +Call for general testing.Mon. May 17, 2021 - RCRelease Candidate packages are built.Updated releases of ROS Desktop[2]packages available.Thu. May 20, 2021 - Distro FreezeFreeze rosdistro. +No PRs for Galactic on therosdistrorepo will be merged (reopens after the release announcement).Sun. May 23, 2021 - General AvailabilityRelease announcement.rosdistrois reopened for Galactic PRs.[1](1,2,3)Theros_corevariant is described inREP 2001 (ros-core).[2](1,2)Thedesktopvariant is described inREP 2001 (desktop-variants). + +Code Examples: + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--log-levelWARN--log-leveltalker:=DEBUG + +Language: unknown +ROS_LOG_DIR=/tmp/fooros2rundemo_nodes_cpptalker + +Language: unknown +ROS_HOME=/path/to/homeros2rundemo_nodes_cpptalker + +Language: unknown +mkdir-pdemo/msgcddemo +cat<< EOF > msg/Demo.msgstd_msgs/Header headergeometry_msgs/Twist twistgeometry_msgs/Accel accelEOF + +Language: unknown +rosidlgenerate-ogen-tc-tcpp-tpy-I$(ros2pkgprefix--sharestd_msgs)/..\-I$(ros2pkgprefix--sharegeometry_msgs)/..demomsg/Demo.msg + +Language: unknown +rosidltranslate-ogen--toidl-I$(ros2pkgprefix--sharestd_msgs)/..\-I$(ros2pkgprefix--sharegeometry_msgs)/..demomsg/Demo.msg + +Language: unknown +importsensor_msgs_py.point_cloud2fromstd_msgs.msgimportHeaderpointlist=[[0.0,0.1,0.2]]pointcloud=sensor_msgs_py.point_cloud2.create_cloud_xyz32(Header(frame_id='frame'),pointlist)forpointinsensor_msgs_py.point_cloud2.read_points(pointcloud):print(point) + +Language: unknown +$ros2topicpub/chatterstd_msgs/msg/String"data: 'hello'" + +Language: unknown +$ros2topicecho--raw/chatter +b'\x00\x01\x00\x00\x06\x00\x00\x00hello\x00\x00\x00'--- + +Language: unknown +#include#includeintmain(){std_msgs::msg::Stringmsg;msg.data="hello world";printf("%s",rosidl_generator_traits::to_yaml(msg).c_str());return0;} + +Language: unknown +$ros2rundemo_nodes_cppparameter_blackboard + +Language: unknown +$ros2paramset/parameter_blackboardfoobar# sets 'foo' parameter to value 'bar'$ros2paramdump/parameter_blackboard# dumps current value of parameters to ./parameter_blackboard.yaml$ros2paramset/parameter_blackboardfoodifferent# sets 'foo' parameter to value 'different'$ros2paramload/parameter_blackboard./parameter_blackboard.yaml# reloads previous state of parameters, 'foo' is back to 'bar' + +Language: unknown +$ros2rundemo_nodes_pytalker_qos-n1000# i.e. best_effort publisher + +Language: unknown +$ros2rundemo_nodes_pylistener_qos--reliable-n1000# i.e. reliable subscription + +Language: unknown +$ros2doctor--report# ...QOSCOMPATIBILITYLIST +topic[type]:/chatter[std_msgs/msg/String]publishernode:talker_qos +subscribernode:listener_qos +compatibilitystatus:ERROR:Besteffortpublisherandreliablesubscription;# ... + +Language: unknown +/**:ros__parameters:launch_date:$(command date) + +Language: unknown +importlaunchimportlaunch_ros.parameter_descriptionsimportlaunch_ros.actionsdefgenerate_launch_description():returnlaunch.LaunchDescription([launch_ros.actions.Node(package='demo_nodes_cpp',executable='parameter_blackboard',parameters=[launch_ros.parameter_descriptions.ParameterFile(param_file='parameter_file_with_substitutions.yaml',allow_substs=True)])]) + +Language: unknown + + +Language: unknown +ros2runexamples_rclcpp_minimal_publisherpublisher_member_function_with_unique_network_flow_endpoints + +Language: unknown +ros2runexamples_rclcpp_minimal_subscribersubscriber_member_function_with_unique_network_flow_endpoints + +Language: unknown +ros2bagrecord--all--max-bag-duration100 + +Language: unknown +$ros2bagliststorage +rosbag2_v2 +sqlite3 + +$ros2baglistconverter +rosbag_v2_converter + +Language: unknown +ros2bagrecord--all--compression-formatzstd--compression-modemessage + +Language: unknown +ros2bagrecord--regex"*scan*" + +Language: unknown +ros2bagrecord--all--exclude"/my_namespace/*" + +Language: unknown +# In one shell$ros2bagplaymy_bag# In another shell$ros2servicelist-t +/rosbag2_player/get_rate[rosbag2_interfaces/srv/GetRate]/rosbag2_player/is_paused[rosbag2_interfaces/srv/IsPaused]/rosbag2_player/pause[rosbag2_interfaces/srv/Pause]/rosbag2_player/play_next[rosbag2_interfaces/srv/PlayNext]/rosbag2_player/resume[rosbag2_interfaces/srv/Resume]/rosbag2_player/set_rate[rosbag2_interfaces/srv/SetRate]/rosbag2_player/toggle_paused[rosbag2_interfaces/srv/TogglePaused]# Check if playback is paused$ros2servicecall/rosbag2_player/is_pausedrosbag2_interfaces/IsPaused# Pause playback$ros2servicecall/rosbag2_player/pauserosbag2_interfaces/Pause# Resume playback$ros2servicecall/rosbag2_player/resumerosbag2_interfaces/Resume# Change the paused state of playback to its opposite. If playing, pauses. If paused, resumes.$ros2servicecall/rosbag2_player/toggle_pausedrosbag2_interfaces/TogglePaused# Get the current playback rate$ros2servicecall/rosbag2_player/get_rate# Set the current playback rate (must be > 0)$ros2servicecall/rosbag2_player/set_raterosbag2_interfaces/SetRate"rate: 0.1"# Play a single next message (only works while paused)$ros2servicecall/rosbag2_player/play_nextrosbag2_interfaces/PlayNext + +Language: unknown +# Publish at default rate - 40Hzros2bagplaymy_bag--clock# Publish at specific rate - 100Hzros2bagplaymy_bag--clock100 + +Language: unknown +ros2runtf2_rostf2_echo--ros-args-r__ns:=/test--odombase_link + +Language: unknown +std::shared_future future; +...-executor.spin_until_future_complete(future);+executor.spin_until_future_complete>(future); + +Language: unknown +constchar*my_const_char_stringformat="Foo";RCLCPP_DEBUG(get_logger(),my_const_char_string); + +Language: unknown +constchar*my_const_char_stringformat="Foo";RCLCPP_DEBUG(get_logger(),"%s",my_const_char_string); + +Language: unknown +RCLCPP_DEBUG(get_logger(),"Foo"); + +Language: unknown +std::stringmy_std_string="Foo";RCLCPP_DEBUG(get_logger(),my_std_string); + +Language: unknown +std::stringmy_std_string="Foo";RCLCPP_DEBUG(get_logger(),"%s",my_std_string.c_str()); + +Language: unknown +// declare integer parameter with default value, trying to set it to a different type will fail.node->declare_parameter("my_int",5);// declare string parameter with no default and mandatory user provided override.// i.e. the user must pass a parameter file setting it or a command line rule -p :=node->declare_parameter("string_mandatory_override",rclcpp::PARAMETER_STRING);// Conditionally declare a floating point parameter with a mandatory override.// Useful when the parameter is only needed depending on other conditions and no default is reasonable.if(mode=="modeA"){node->declare_parameter("conditionally_declare_double_parameter",rclcpp::PARAMETER_DOUBLE);}// You can also get the old dynamic typing behavior if you want:rcl_interfaces::msg::ParameterDescriptordescriptor;descriptor.dynamic_typing=true;node->declare_parameter("dynamically_typed_param",rclcpp::ParameterValue{},descriptor); + +Language: unknown +importrclpyimportrclpy.nodefromrcl_interfaces.msgimportParameterTypefromrcl_interfaces.msgimportSetParametersResultrclpy.init()node=rclpy.node.Node('callback_example')node.declare_parameter('my_param','initial value')defon_parameter_event(parameter_list):forparameterinparameter_list:node.get_logger().info(f'Got{parameter.name}={parameter.value}')returnSetParametersResult(successful=True)node.add_on_set_parameters_callback(on_parameter_event)rclpy.spin(node) + +Language: unknown +ros2paramset/callback_examplemy_param"Hello World" + +Language: unknown +importrclpyimportrclpy.nodefromrcl_interfaces.msgimportParameterDescriptorrclpy.init()node=rclpy.node.Node('static_param_example')node.declare_parameter('static_param','initial value')node.declare_parameter('dynamic_param','initial value',descriptor=ParameterDescriptor(dynamic_typing=True))rclpy.spin(node) + +Language: unknown +$ros2paramset/static_param_exampledynamic_param42Set parameter successful$ros2paramset/static_param_examplestatic_param42Setting parameter failed: Wrong parameter type, expected 'Type.STRING' got 'Type.INTEGER' + +Language: unknown +importrclpy.qospublisher_profile=rclpy.qos.qos_profile_sensor_datasubscription_profile=rclpy.qos.qos_profile_parameter_eventsprint(rclpy.qos.qos_check_compatible(publisher_profile,subscription_profile)) + +Language: unknown +$python3qos_check_compatible_example.py(QoSCompatibility.ERROR, 'ERROR: Best effort publisher and reliable subscription;') + +Language: unknown +voidgoal_response_callback(std::shared_futurefuture) + +Language: unknown +voidgoal_response_callback(GoalHandleFibonacci::SharedPtrgoal_handle) + +Language: unknown +rcl_ret_trcl_lifecycle_state_machine_init(rcl_lifecycle_state_machine_t*state_machine,rcl_node_t*node_handle,constrosidl_message_type_support_t*ts_pub_notify,constrosidl_service_type_support_t*ts_srv_change_state,constrosidl_service_type_support_t*ts_srv_get_state,constrosidl_service_type_support_t*ts_srv_get_available_states,constrosidl_service_type_support_t*ts_srv_get_available_transitions,constrosidl_service_type_support_t*ts_srv_get_transition_graph,constrcl_lifecycle_state_machine_options_t*state_machine_options); + +Language: unknown +rcl_ret_trcl_lifecycle_state_machine_fini(rcl_lifecycle_state_machine_t*state_machine,rcl_node_t*node_handle); + +Language: unknown +explicitLifecycleNode(conststd::string&node_name,constrclcpp::NodeOptions&options=rclcpp::NodeOptions(),boolenable_communication_interface=true); + +Language: unknown +ros2topiclist--no-daemon diff --git "a/exported_docs/ros2/Galactic_Geochelone_changelog\357\203\201.txt" "b/exported_docs/ros2/Galactic_Geochelone_changelog\357\203\201.txt" new file mode 100644 index 0000000..e241768 --- /dev/null +++ "b/exported_docs/ros2/Galactic_Geochelone_changelog\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Galactic Geochelone changelog +URL: https://docs.ros.org/en/jazzy/Releases/Galactic-Geochelone-Complete-Changelog.html +Section: Installation +-------------------------------------------------------------------------------- + +Galactic Geochelone changelogThis page is a list of the complete changes in all ROS 2 core packages since the previous release.Table of Contentsaction_msgsaction_tutorials_cppaction_tutorials_interfacesaction_tutorials_pyactionlib_msgsament_clang_formatament_clang_tidyament_cmakeament_cmake_autoament_cmake_clang_formatament_cmake_clang_tidyament_cmake_copyrightament_cmake_coreament_cmake_cppcheckament_cmake_cpplintament_cmake_export_definitionsament_cmake_export_dependenciesament_cmake_export_include_directoriesament_cmake_export_interfacesament_cmake_export_librariesament_cmake_export_link_flagsament_cmake_export_targetsament_cmake_flake8ament_cmake_gmockament_cmake_google_benchmarkament_cmake_gtestament_cmake_include_directoriesament_cmake_librariesament_cmake_lint_cmakeament_cmake_mypyament_cmake_noseament_cmake_pclintament_cmake_pep257ament_cmake_pycodestyleament_cmake_pyflakesament_cmake_pytestament_cmake_pythonament_cmake_rosament_cmake_target_dependenciesament_cmake_testament_cmake_uncrustifyament_cmake_versionament_cmake_xmllintament_copyrightament_cppcheckament_cpplintament_flake8ament_index_cppament_index_pythonament_lintament_lint_autoament_lint_cmakeament_lint_commonament_mypyament_packageament_pclintament_pep257ament_pycodestyleament_pyflakesament_uncrustifyament_xmllintbuiltin_interfacescamera_calibration_parserscamera_info_managerclass_loadercommon_interfacescompositioncomposition_interfacescycloneddsdemo_nodes_cppdemo_nodes_cpp_nativedemo_nodes_pydiagnostic_msgsdomain_coordinatordummy_map_serverdummy_robot_bringupdummy_sensorsexample_interfacesexamples_rclcpp_cbg_executorexamples_rclcpp_minimal_action_clientexamples_rclcpp_minimal_action_serverexamples_rclcpp_minimal_clientexamples_rclcpp_minimal_compositionexamples_rclcpp_minimal_publisherexamples_rclcpp_minimal_serviceexamples_rclcpp_minimal_subscriberexamples_rclcpp_minimal_timerexamples_rclcpp_multithreaded_executorexamples_rclpy_executorsexamples_rclpy_guard_conditionsexamples_rclpy_minimal_action_clientexamples_rclpy_minimal_action_serverexamples_rclpy_minimal_clientexamples_rclpy_minimal_publisherexamples_rclpy_minimal_serviceexamples_rclpy_minimal_subscriberexamples_rclpy_pointcloud_publisherexamples_tf2_pyfastrtps_cmake_modulegeometry2geometry_msgsgoogle_benchmark_vendorimage_commonimage_toolsimage_transportinteractive_markersintra_process_demokdl_parserlaser_geometrylaunchlaunch_roslaunch_testinglaunch_testing_ament_cmakelaunch_testing_roslaunch_xmllaunch_yamllibcurl_vendorlibstatistics_collectorlibyaml_vendorlifecyclelifecycle_msgslogging_demomap_msgsmessage_filtersmimick_vendornav_msgsosrf_pycommonosrf_testing_tools_cpppendulum_controlpendulum_msgsperformance_test_fixturepluginlibpybind11_vendorpython_cmake_modulepython_qt_bindingqt_dotgraphqt_guiqt_gui_cppquality_of_service_demo_cppquality_of_service_demo_pyrclrcl_actionrcl_interfacesrcl_lifecyclercl_logging_interfacercl_logging_log4cxxrcl_logging_nooprcl_logging_spdlogrcl_yaml_param_parserrclcpprclcpp_actionrclcpp_componentsrclcpp_lifecyclerclpyrcpputilsrcutilsresource_retrieverrmwrmw_connextddsrmw_connextdds_commonrmw_connextddsmicrormw_cyclonedds_cpprmw_dds_commonrmw_fastrtps_cpprmw_fastrtps_dynamic_cpprmw_fastrtps_shared_cpprmw_implementationrmw_implementation_cmakerobot_state_publisherros1_bridgeros2actionros2bagros2cliros2cli_common_extensionsros2cli_test_interfacesros2componentros2doctorros2interfaceros2launchros2lifecycleros2lifecycle_test_fixturesros2multicastros2noderos2paramros2pkgros2runros2serviceros2testros2topicros_testingrosbag2rosbag2_compressionrosbag2_compression_zstdrosbag2_cpprosbag2_interfacesrosbag2_performance_benchmarkingrosbag2_pyrosbag2_storagerosbag2_storage_default_pluginsrosbag2_test_commonrosbag2_testsrosbag2_transportrosgraph_msgsrosidl_adapterrosidl_clirosidl_cmakerosidl_default_generatorsrosidl_default_runtimerosidl_generator_crosidl_generator_cpprosidl_generator_dds_idlrosidl_generator_pyrosidl_parserrosidl_runtime_crosidl_runtime_cpprosidl_runtime_pyrosidl_typesupport_crosidl_typesupport_cpprosidl_typesupport_fastrtps_crosidl_typesupport_fastrtps_cpprosidl_typesupport_interfacerosidl_typesupport_introspection_crosidl_typesupport_introspection_cpprpyutilsrqtrqt_actionrqt_bagrqt_bag_pluginsrqt_consolerqt_graphrqt_guirqt_gui_cpprqt_gui_pyrqt_msgrqt_plotrqt_publisherrqt_py_commonrqt_py_consolerqt_reconfigurerqt_service_callerrqt_shellrqt_srvrqt_toprqt_topicrti_connext_dds_cmake_modulerttestrviz2rviz_assimp_vendorrviz_commonrviz_default_pluginsrviz_ogre_vendorrviz_renderingrviz_rendering_testsrviz_visual_testing_frameworksensor_msgssensor_msgs_pyshape_msgsshared_queues_vendorspdlog_vendorsqlite3_vendorsros2statistics_msgsstd_msgsstd_srvsstereo_msgstango_icons_vendortest_clitest_cli_remappingtest_communicationtest_interface_filestest_launch_rostest_launch_testingtest_msgstest_quality_of_servicetest_rclcpptest_rmw_implementationtest_securitytest_tf2tf2tf2_bullettf2_eigentf2_eigen_kdltf2_geometry_msgstf2_kdltf2_msgstf2_pytf2_rostf2_ros_pytf2_sensor_msgstf2_toolstlsftlsf_cpptopic_monitortopic_statistics_demotracetoolstracetools_launchtracetools_testtracetools_tracetrajectory_msgsturtlesimunique_identifier_msgsurdfurdf_parser_pluginvisualization_msgsyaml_cpp_vendorzstd_vendoraction_msgsChange index.ros.org -> docs.ros.org. (#122)Updating Quality Declaration (#120)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannaction_tutorials_cppUpdate logging macros (#476)Update the package.xml files with the latest Open Robotics maintainers (#466)Update goal response callback signature (#463)Contributors: Audrow Nash, Jacob Perron, Michael Jeronimoaction_tutorials_interfacesUpdate the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimoaction_tutorials_pyUse underscores instead of dashes in setup.cfg (#502)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Ivan Santiago Paunovic, Michael Jeronimoactionlib_msgsUpdate package maintainers. (#132)Contributors: Michel Hidalgoament_clang_formatRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Add clang-format-version option to ament_clang_format (#282)Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Logan, Tyler Weaverament_clang_tidyRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Add multiprocessing support to ament_clang_tidy (#288) * add multiprocessing support * fix stylistic lint issuesAdd –packages-select argument to ament_clang_tidy (#287) Add comment explaining handling quoted list of space separated package names Update documentation for ament_clang_tidyUpdate maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, M. Mei, Tyler Weaverament_cmakeUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_autoUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_clang_formatRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_cmake_clang_tidyRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3add TIMEOUT argument to ament_cmake_clang_tidy (#298)Add Audrow as a maintainer (#294)Fix documentation for ament_cmake_clang_tidy (#285)Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, M. Mei, Tyler Weaverament_cmake_copyrightRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsincrease default timeout for CMake copyright linter to 120s (#261)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Dirk Thomas, Scott K Loganament_cmake_coreMerge pull request#287from ament/mjeronimo/add-condition-support * Check condition attr in package.xml dependencies The condition attribute was already parsed when reading the XML file. Just needed to check the condition when adding dependencies to the list for a particular key/target. Fixes#266* Address Dirk’s code review feedbackAddress Dirk’s code review feedbackCheck condition attr in package.xml dependencies The condition attribute was already parsed when reading the XML file. Just needed to check the condition when adding dependencies to the list for a particular key/target. Fixes#266Update package maintainers. (#286)Contributors: Michael Jeronimo, Michel Hidalgoament_cmake_cppcheckRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsIncrease the ament_cppcheck timeout to 5 minutes. (#271) This will avoid timeouts on some slower platforms that we’ve started to see.parse LANGUAGE argument case insensitive (#255)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Karsten Knese, Scott K Loganament_cmake_cpplintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_cmake_export_definitionsUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_export_dependenciesfix cmake list(TRANSFORM ) is only available from version 3.12, (#296) convert to string insteadfix imported targets with multiple configuration (#290) * fix imported targets with multiple configuration * taking into account DEBUG_CONFIGURATIONS global variableUpdate package maintainers. (#286)Contributors: Michel Hidalgo, siposcsaba89ament_cmake_export_include_directoriesUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_export_interfacesUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_export_librariesFix variable name in ament_export_libraries.cmake (#314)Update package maintainers. (#286)Contributors: Alejandro Hernández Cordero, Michel Hidalgoament_cmake_export_link_flagsUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_export_targetsUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_flake8Remove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wangament_cmake_gmockUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_google_benchmarkSerialize benchmarks within CTest by default (#308)Handle runtime failures in Google Benchmark (#294) This change will handle runtime failures in Google Benchmark by propagating error information from Google Benchmark to both CTest and the Jenkins benchmark plugin.Use consistent string format and resolve flake8 (#295) Follow-up to a5fb3112b5c46c42b1824c96af4171d469eb13bfMake ament_cmake_test a dep of ament_cmake_google_benchmark (#293)Catch JSONDecodeError and printout some debug info (#291)Update package maintainers. (#286)Make AMENT_RUN_PERFORMANCE_TESTS a CMake option (#280)Skip performance tests using a CMake variable (#278) These tests can be fairly heavy, so we don’t want to run them by default. It would be better if there was a way to skip the tests by default in such a way that they could be specifically un-skipped at runtime, but I can’t find a mechanism in CMake or CTest that would allow us to achieve that behavior without leveraging environment variables.Handle Google Benchmark ‘aggregate’ results (#276) Previously, I assumed all results generated by Google Benchmark were of ‘iteration’ type. Now that I have more experience with Google Benchmark, I’ve started generating aggregate results, which contain some different properties. This change adds support for aggregate results and should make it easy to add any other result schemas we encounter in the future. For forward-compatibility, unsupported types will generate a warning message but will not fail the test. This makes the conversion tolerant to Google Benchmark adding new measures for existing mechanisms.Initial Google Benchmark results conversion (#275)Handle missing results file for Google Benchmark (#265)Initial ament_cmake_google_benchmark package (#261)Contributors: Michel Hidalgo, Scott K Logan, brawnerament_cmake_gtestDisable gtest warning when building in Release (#298)https://github.com/google/googletest/issues/1303Update package maintainers. (#286)[ament_cmake_gtest] ensure gtest to consume the correct headers. (#267) * ensure gtest to consume the correct headers. * add another patch.Contributors: Michel Hidalgo, Sean Yen, Victor Lopezament_cmake_include_directoriesUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_librariesUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_lint_cmakeRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.ament_lint_cmake: default linelength in argumentparser for consistency (#306)0.10.3Fix ament_lint_cmake line length expression (#236) This regular expression is using the re.VERBOSE flag, meaning that characters after an un-escaped ‘#’ character are interpreted as a comment and are not part of the expression. Also set the default maximum line length to 140 columns.Add Audrow as a maintainer (#294)Make CMake linter line length configurable (#235) Co-authored-by: Miaofei Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Emerson Knapp, Scott K Loganament_cmake_mypyRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wangament_cmake_noseUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_pclintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_cmake_pep257Remove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_cmake_pycodestyleRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_cmake_pyflakesRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_cmake_pytestFix ament_get_pytest_cov_version for newer versions of pytest (#315)Update package maintainers. (#286)Contributors: Christophe Bedard, Michel Hidalgoament_cmake_pythonSymlink setup.cfg and sources before building Python egg-info (#327)Simplify ament_python_install_package() macro. (#326) Do not delegate to setuptools, install egg-info manually.Escape $ENV{DESTDIR} everywhere in ament_python_install_package() (#324) Follow up after f80071e2216e766f7bf1b0792493a5f6523e9226Use DESTDIR on ament_python_install_package() (#323) * Use DESTDIR on ament_python_install_package()Make ament_python_install_package() install a flat Python egg (#316)[ament_cmake_python] ament_cmake_python_get_python_install_dir public (#300) * [ament_cmake_python] make the ament_cmake_python_get_python_install_dir a public interface.Update package maintainers. (#286)Contributors: Michel Hidalgo, Naveauament_cmake_rosUpdate package maintainers. (#11)Contributors: Michel Hidalgoament_cmake_target_dependenciesForce SYSTEM keyword in ament_target_dependencies() at the start. (#303)Add SYSTEM keyword option to ament_target_dependencies (#297) * Add SYSTEM keyword option to ament_target_dependencies * Add documentation of SYSTEM keyword for ament_target_dependenciesUpdate package maintainers. (#286)ordered interface include dirs and use privately to ensure workspace order (#260)Contributors: Andre Nguyen, Dirk Thomas, Michel Hidalgoament_cmake_testUpdate package maintainers. (#286)Fix skipped test reporting in CTest (#279) This is a follow-up to c67cdf2. When the SKIP_RETURN_CODE gets set to 0, the value is interpreted as ‘false’, and the test property is never actually added.limit test time to three decimals (#271)Add actual test time to xUnit result files (#270) * Add actual test time to xUnit result files Fixes#269* Report test_time even with skipped test * Set time attribute for testcase elementAdd SKIP_RETURN_CODE argument to ament_add_test (#264) This makes therun_test.pywrapper aware of theSKIP_RETURN_CODEproperty on CTest tests. In the existing implementation, the wrapper detects that no result file was generated and overrides the special return code coming from the test, making the the CTest feature fail completely. This change makes the wrapper script aware of the special return code, and when detected, will write a ‘skipped’ result file instead of a ‘failed’ result file, and pass along the special return code as-is. Now the gtest result and the ctest results both show the test as ‘skipped’ when the special return flag is used. Note that none of this behavior is enabled by default, which is important because we wouldn’t want a test to fail and return a code which we’ve decided is the special ‘skip’ return code. Only tests which are aware of this feature should use it.Contributors: Dirk Thomas, Michel Hidalgo, Ruffin, Scott K Loganament_cmake_uncrustifyRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsparse LANGUAGE argument case insensitive (#255)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Karsten Knese, Scott K Loganament_cmake_versionUpdate package maintainers. (#286)Contributors: Michel Hidalgoament_cmake_xmllintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_copyrightRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.Use non-blind except for open() (#307)Add optional file header style (#304) * Add optional file header style * Fix test on ament_copyright0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8add mit-0 as a valid license to ament_copyright (#284)Support Python 3.8-provided importlib.metadata (#290) The importlib_metadata package is a backport of the importlib.metadata module from Python 3.8. Fedora (and possibly others) no longer package importlib_metadata because they ship Python versions which have the functionality built-in.Update maintainer (#274) * update maintainer * add authorsadded bsd 2 clause simplified license to ament_copyright (#267) * added bsd 2 clause simplified license to ament_copyrightRemove use of pkg_resources from ament_lint. (#260) Replace it with the use of the more modern importlib_metadata library. There are a couple of reasons to do this: 1. pkg_resources is quite slow to import; on my machine, just firing up the python interpreter takes ~35ms, while firing up the python interpreter and importing pkg_resources takes ~175ms. Firing up the python interpreter and importing importlib_metadata takes ~70ms. Removing 100ms per invocation of the command-line both makes it speedier for users, and will speed up our tests (which call out to the command-line quite a lot). 2. pkg_resources is somewhat deprecated and being replaced by importlib.https://importlib-metadata.readthedocs.io/en/latest/using.htmldescribes some of it Note: By itself, this change is not enough to completely remove our dependence on pkg_resources. We’ll also have to do something about the console_scripts that setup.py generates. That will be a separate effort.Add pytest.ini so local tests don’t display warning. (#259)Contributors: Alfi Maulana, Audrow Nash, Chris Lalancette, Christophe Bedard, Claire Wang, Evan Flynn, M. Mei, Scott K Loganament_cppcheckRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Fix file exclusion behavior in ament_cppcheck and ament_cpplint (#299) * fix exclude behavior in ament_cppcheck and ament_cpplint * fix flake8 errors * add missing realpath() conversionAdd Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Suppress unknownMacro (#268) cppcheck creates an unknownMacro error when it cannot resolve a macro. Since we don’t pass in all dependent headers, we don’t expect all macros to be discoverable by cppcheck.Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Dan Rose, M. Mei, Scott K Loganament_cpplintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Fix file exclusion behavior in ament_cppcheck and ament_cpplint (#299) * fix exclude behavior in ament_cppcheck and ament_cpplint * fix flake8 errors * add missing realpath() conversionAdd Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, M. Mei, Scott K Loganament_flake8Remove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wangament_index_cppRemove Claire as the maintainer. (#71)Change links from index.ros.org -> docs.ros.org (#70)Add Audrow as a maintainer (#68)update maintainers (#67)Update QD to Quality Level 1 (#66)add rational why ament_index pkgs don’t have explicit performance tests (#65)Fixed Doxygen warnings (#63)Remove the Quality Level from the README.md. (#62)Update QD ament_index_cpp to QL 2 (#59)Add Security Vulnerability Policy pointing to REP-2006. (#57)[Quality Declaration] Update Version Stability to stable version (#58)Contributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Claire Wang, Dirk Thomas, brawnerament_index_pythonRemove Claire as the maintainer. (#71)Change links from index.ros.org -> docs.ros.org (#70)Add Audrow as a maintainer (#68)update maintainers (#67)add rational why ament_index pkgs don’t have explicit performance tests (#65)Remove the Quality Level from the README.md. (#62)Fix document link (#61)[Quality Declaration] Update Version Stability to stable version (#58)Contributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Claire Wang, Dirk Thomas, Matthijs van der Burghament_lintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_lint_autoRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Use correct lint package dependencies (#278)Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Esteve Fernandez, Scott K Loganament_lint_cmakeRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.ament_lint_cmake: default linelength in argumentparser for consistency (#306)0.10.3Fix ament_lint_cmake line length expression (#236) This regular expression is using the re.VERBOSE flag, meaning that characters after an un-escaped ‘#’ character are interpreted as a comment and are not part of the expression. Also set the default maximum line length to 140 columns.Add Audrow as a maintainer (#294)Make CMake linter line length configurable (#235) Co-authored-by: Miaofei Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Emerson Knapp, Scott K Loganament_lint_commonRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsContributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_mypyRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wangament_packageRevert “Generate Setuptools Dict Helper Method (#126)” (#131)Generate Setuptools Dict Helper Method (#126)Add Audrow as a maintainer (#127)Support Python 3.8-provided importlib.metadata (#124)Declare missing dependency on python3-importlib-resources (#123)make AMENT_TRACE_SETUP_FILES output sourceable (#120)update maintainersSwitch ament_package to using importlib. (#118)Add pytest.ini so local tests don’t display warning (#117)add configure-time flag to skip parent_prefix_path (#115)Contributors: Audrow Nash, Chris Lalancette, David V. Lu!!, Dirk Thomas, Mabel Zhang, Scott K Loganament_pclintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Add pytest marks to ament_pclint tests. (#202) * Add pytest marks to ament_pclint tests. * fix failed tests Co-authored-by: Miaofei Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Logan, Steven! Ragnarökament_pep257Remove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsremove use of “extend” action in argparse (#262)Expand ignores to pep257 definition. (#241) * Expand ignores to pep257 definition. (ament#240) * add ‘–allow-undocumented’ flag to enforce pep257 * restore existing default error codes to check * fix no-ignores logic * expose options from pydocstyle * allow user to explicitly set convention to “ament” * fix typo in populating argv for pydocstyle * reformat ament convention list * Add help info for ament conventionAdd pytest.ini so local tests don’t display warning. (#259)remove match args to allow pydocstyle defaults (#243)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Logan, Ted Kernament_pycodestyleRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_pyflakesRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganament_uncrustifyRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Allow ‘C++’ as language, but convert it to ‘CPP’ (#302)Allow correct languages on uncrustify (#272) * Allow correct languages on uncrustify. * Update dictionary.Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Miguel Company, Scott K Loganament_xmllintRemove Claire as a maintainer. (#312) * Remove Claire as a maintainer. * Remove dead email addresses. * Remove more dead email addresses. * Switch setup.py maintainer to Audrow.0.10.3Add Audrow as a maintainer (#294)Drop trailing tab from package manifests (#291) Follow-up to 8bf194aa1ac282db5483dd0d3fefff8f325b0db8Update maintainer (#274) * update maintainer * add authorsAdd pytest.ini so local tests don’t display warning. (#259)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Scott K Loganbuiltin_interfacesChange index.ros.org -> docs.ros.org. (#122)Updating Quality Declaration (#120)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Document that Time and Duration are explictly ROS Time (#103)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, Tully Foote, brawner, shonigmanncamera_calibration_parsersFix formatting and include paths for linters (#157)ROS2 Using the filesystem helper in rcpputils (#133)[Windows][ros2] Avoid build break for Visual Studio 2019 v16.3 (#135)Camera Calibration Parsers ROS2 Port (#105)Image Transport ROS2 port (#84)Use Boost_LIBRARIES instead of Boost_PYTHON_LIBRARY This was causing issues when building with python3 since thenBoost_PYTHON_LIBRARYis not set, instead cmake setsBoost_PYTHON3_LIBRARY. So instead of adding each library separately, usingBoost_LIBRARIESseems to be better. For reference, from the cmake docs:`Boost_LIBRARIES-BoostcomponentlibrariestobelinkedBoost\__LIBRARY-Librariestolinkforcomponent`Properly detect Boost Python 2 or 3 This fixes#591.11.11update changelogsAdd install target for python wrapper libraryOnly link against needed Boost libraries 9829b02 introduced a python dependency into find_package(Boost..) which results in ${Boost_LIBRARIES} containing boost_python and such a dependency to libpython at link time. With this patch we only link against the needed libraries.Add python wrapper for readCalibration. Reads .ini or .yaml calibration file and returns camera name and sensor_msgs/cameraInfo.Use $catkin_EXPORTED_TARGETSRemove no-longer-neccessary flags to allow OS X to use 0.3 and 0.5 of yaml-cpp.remove buggy CMake messagefix#39make sure test does not fail[camera_calibration_parsers] Better error message when calib file can’t be writtenadd rosbash as a test dependencyadd a test dependency now that we have testsparse distortion of arbitraty length in INI This fixes#33add a test to parse INI calibration files with 5 or 8 D paramAdd yaml-cpp case for building on AndroidFix catkin_make failure (due to yaml-cpp deps) for mac osfix bad yaml-cpp usage in certain conditions fixes#24add a dependency on pkg-config to have it work on Indigofix YAML CPP 0.5.x compatibilityContributors: Andreas Klintberg, Gary Servin, Helen Oleynikova, Isaac IY Saito, Jochen Sprickerhof, Kartik Mohta, Markus Roth, Martin Idel, Michael Carroll, Sean Yen, Vincent Rabaud, Yifei Zhangcamera_info_managerFix formatting and include paths for linters (#157)Enable Windows build. (#159)Fix abort criteria for setCameraInfoService callback (#132)camera_info_manager ROS2 port (#94)Image Transport ROS2 port (#84)Fix the find_package(catkin) redundancyAdd a dependency between the test and the test executableAdd camera_calibration_parsers dependency to camera_info_manager1.11.11update changelogsReturn empty CameraInfo when !ros::ok()Return empty CameraInfo when !ros::ok()fix compilation on Fedora, fixes#42simplify target_link_libraries That should fix#35Add public member function to manually set camera info (#19)make rostest in CMakeLists optional (ros/rosdistro#3010)check for CATKIN_ENABLE_TESTINGadd Jack as maintaineradd gtest libraries linkagefix the rostest dependencyfix catkin gtest and rostest problemfix unit test dependenciesRemoved duplicated test dependancy Test dependencies should never duplicate build or run dependencies.fix the urlsUpdated package.xml file(s) to handle new catkin buildtool_depend requirementremove the brief attributefix bad folder/librariesadd missing rostest dependencyfix bad dependencyfix dependenciesadd catkin as a dependencycomply to the catkin APIadd missing linkageinstall the include directoriesfix build issuesmake the libraries publicAPI documentation review updatesuppress misleading camera_info_manager error messages [#5273]remove deprecated global CameraInfoManager symbol for Fuerte (#4971)Revert to using boost::mutex, not boost::recursive_mutex.Hack saveCalibrationFile() to stat() the containing directory and attempt to create it if necessary. Test for this case.Reload camera info when camera name changes.Implement most new Electric API changes, with test cases.Add ${ROS_HOME} expansion, with unit test cases. Do not use “$$” for a single ‘$’, look for “${” instead.Use case-insensitive comparisons for parsing URL tags (#4761). Add unit test cases to cover this. Add unit test case for camera name containing video mode.add test for resolving an empty URLDeprecate use of global CameraInfoManager symbol in E-turtle (#4786). Modify unit tests accordingly.provide camera_info_manager namespace, fixes #4760Add support for “package://” URLs.Fixed tests to work with new CameraInfo.Moved image_common from camera_drivers.Contributors: Aaron Blasdel, Enrique Fernandez, Jack O’Quin, Jonathan Bohren, Joseph Schornak, Lukas Bulwahn, Martin Idel, Max Schettler, Michael Carroll, Sean Yen, Vincent Rabaud, blaise, mihelich, mirzashahclass_loaderRemove travis. (#182)Change index.ros.org -> docs.ros.org. (#181)Fix ternary null check found by clang static analysis (#176)Update QD to QL 1 (#177)Updated console_bridge QL in QDUpdate package maintainers. (#169)enable building a static library (#163)Update Quality Declaration to reflect QL 2 (#160).Increase coverage with a graveyard behavior test and unmanaged instance test (#159)Add Security Vulnerability Policy pointing to REP-2006. (#157)Clean up and improve documentation (#156)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Dirk Thomas, Michel Hidalgo, Stephen Brawner, ahcorde, brawnercommon_interfacesUpdate package maintainers. (#132)Contributors: Michel HidalgocompositionFix leak(#480) (#481)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimo, y-okumura-ispcomposition_interfacesChange index.ros.org -> docs.ros.org. (#122)Updating Quality Declaration (#120)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmanncycloneddsDATA_AVAILABLE was not always triggered when by a dispose and sometimes triggered in the absence of an observable state change (arrival of a dispose for an already-disposed instance where the dispose had not yet been read);Restores functionality of the “raw ethernet” mode as well as IPv6 with link-local addresses, both accidentally broken in 0.6.0;Fixes a crash in processing endpoint discovery data containing unrecognised locator kinds;Fixes type conversion for local historical data (e.g., mixed use of ROS 2 C/C++ type supports in combination with transient-local endpoints within a single process);Fixes a use-after-free of “lease” objects with manual-by-topic writers;Mark instance as “alive” in the reader history and generate an invalid sample to notify the application even if the sample itself is dropped because the same or a later one is present already (e.g., on reconnecting to a transient-local writer);Fix a crash when doing an instance lookup on a built-in topic using the key value;No longer auto-dispose instances as soon as some registered writer disappears, instead do it only when all of them have unregistered it;Fix performance of read_instance and take_instance by performing a proper instance lookup.demo_nodes_cppFix small print issue in allocator tutorial. (#509) (#512)Small fixes for even_parameters_node. (#500)change ParameterEventHandler to take events as const ref instead of shared pointer (#494)Fix integer type in RCLCPP_* macro printf. (#492)Add a demo for the new ParameterEventHandler class (#486)Filter qos overrides in paramter events demos (#491)Update code now that parameter types are static by default (#487)Update logging macros (#476)Make sure to wait for the service before declaring events. (#473)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Michael Jeronimo, William Woodalldemo_nodes_cpp_nativeUpdate demo_nodes_cpp_native to new Fast DDS API (#493)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimo, Miguel Companydemo_nodes_pyUse underscores instead of dashes in setup.cfg (#502)Update deprecated qos policy value names (#468)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Ivan Santiago Paunovic, Michael Jeronimodiagnostic_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmanndomain_coordinatorUpdate package maintainers. (#11)Add pytest.ini to suppress warning output locally. (#8)Contributors: Chris Lalancette, Michel Hidalgodummy_map_serverUpdate the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimodummy_robot_bringupUpdate the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimodummy_sensorsUpdate the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimoexample_interfacesChange links from index.ros.org -> docs.ros.org. (#13)Update maintainer. (#12)Contributors: Chris Lalancette, Jacob Perronexamples_rclcpp_cbg_executorFix clang warnings about type mismatches. (#309)Support for cbg_executor package on QNX (#305)Demo for callback-group-level executor concept. (#302)Contributors: Chris Lalancette, Ralph Lange, joshua-qnxexamples_rclcpp_minimal_action_clientUpdate maintainers (#292)Update goal response callback signature (#291)Make sure to include what you use in all examples. (#284)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jacob Perron, Shane Loretzexamples_rclcpp_minimal_action_serverUpdate maintainers (#292)Make sure to include what you use in all examples. (#284)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Shane Loretzexamples_rclcpp_minimal_clientUpdate maintainers (#292)Make sure to include what you use in all examples. (#284)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Shane Loretzexamples_rclcpp_minimal_compositionUpdate maintainers (#292)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Shane Loretzexamples_rclcpp_minimal_publisherUnique network flows (#296)Update maintainers (#292)Make sure to include what you use in all examples. (#284)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Ananya Muddukrishna, Chris Lalancette, Shane Loretzexamples_rclcpp_minimal_serviceUpdate maintainers (#292)Make sure to include what you use in all examples. (#284)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Shane Loretzexamples_rclcpp_minimal_subscriberUnique network flows (#296)Update maintainers (#292)Make sure to include what you use in all examples. (#284)Remove a TODO in the not_composable demo. (#285)Add Topic Statistics Example (#281)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Ananya Muddukrishna, Chris Lalancette, Devin Bonnie, Shane Loretzexamples_rclcpp_minimal_timerUpdate maintainers (#292)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Shane Loretzexamples_rclcpp_multithreaded_executorUsechar*in logging macros (#295)Update maintainers (#292)Added common linters (#265)Contributors: Alejandro Hernández Cordero, Audrow Nash, Shane Loretzexamples_rclpy_executorsUse underscores instead of dashes in setup.cfg (#310)Update maintainers (#292)Contributors: Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_guard_conditionsUse underscores instead of dashes in setup.cfg (#310)Update maintainers (#292)[rclpy] Create a package with an example showing how guard conditions work (#283)Contributors: Audrow Nash, Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_minimal_action_clientUse underscores instead of dashes in setup.cfg (#310)Using asyncio with ros2 action client (#301)Update maintainers (#292)Added missing linting tests (#287)Contributors: Allison Thackston, Ivan Santiago Paunovic, Shane Loretz, alemmeexamples_rclpy_minimal_action_serverUse underscores instead of dashes in setup.cfg (#310)Update maintainers (#292)Added missing linting tests (#287)Contributors: Allison Thackston, Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_minimal_clientUse underscores instead of dashes in setup.cfg (#310)Remove bare exception catching (#299)Update maintainers (#292)Contributors: Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_minimal_publisherUse underscores instead of dashes in setup.cfg (#310)Update maintainers (#292)Contributors: Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_minimal_serviceUse underscores instead of dashes in setup.cfg (#310)Update maintainers (#292)Contributors: Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_minimal_subscriberUse underscores instead of dashes in setup.cfg (#310)Update maintainers (#292)Contributors: Ivan Santiago Paunovic, Shane Loretzexamples_rclpy_pointcloud_publisherUse underscores instead of dashes in setup.cfg (#310)add pointcloud publisher example (#276)Contributors: Evan Flynn, Ivan Santiago Paunovicexamples_tf2_pyUse underscores instead of dashes in setup.cfg. (#403) (#404)Update maintainers of the ros2/geometry2 fork. (#328)Add pytest.ini so local tests don’t display warning (#276)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Chris Lalancettefastrtps_cmake_moduleupdating quality declaration links (re:ros2/docs.ros2.org#52) (#69)Use CMake config dirs as hint for header/library search (#56)Update package maintainers (#55)QD Update Version Stability to stable version (#46)Contributors: Alejandro Hernández Cordero, Dirk Thomas, Michel Hidalgo, shonigmanngeometry2Port eigen_kdl.h/cpp to ROS2 (#311)Update maintainers of the ros2/geometry2 fork. (#328)Contributors: Chris Lalancette, Jafar Abdigeometry_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Finish up API documentation (#123)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmanngoogle_benchmark_vendorShrink the size of the tz_offset variable. (#13)Update the patching to work on Windows without admin. (#11)Always preserve source permissions in vendor packages. (#12)Update package maintainers. (#10)Upgrade google benchmark from v1.5.1 to v1.5.2 to include QNX patch. (#9)Set the SOVERSION on benchmark libraries. (#8)Set minimum criteria for system package. (#3)Work around warnings building Google Benchmark w/Clang. (#2)Initial google_benchmark_vendor package. (#1)Initial commit.Contributors: Ahmed Sobhy, Chris Lalancette, Michel Hidalgo, Scott K Loganimage_common[ros2] image_common metapackage (#129)1.11.11update changelogsadd Jack as maintainercomply to REP 0127add missing descriptiondefine metapackageContributors: Vincent Rabaud, chapulinaimage_toolsInitialize time stamp for published image messages (#475)Update the package.xml files with the latest Open Robotics maintainers (#466)Added more parameters for camera topic examples (#465)Contributors: Jacob Perron, Michael Jeronimoimage_transportFix formatting and include paths for linters (#157)Fix QoS initialization from RMW QoS profile (#158)add missing set header (#140)Update to use new count APIs (#128)use latest ros2 API (#127)Update ROS2 branch to account for new NodeOptions interface (#120)camera_info_manager ROS2 port (#94)Pointer api updates (#104)Fix rcutils API change by just removing it. (#103)[ROS2] corrections to remapping for raw images (#97)Make ROS2 ImageTransport conform to old api (#88)Image Transport ROS2 Port (#84)Disable image publisher plugins by name (#60) * Disable publisher plugins by name * Now have per publisher blacklist instead of image_transport wide.update to use non deprecated pluginlib macroExtend documentation ofgetCameraInfoTopicDocument the fact that thebase_topicargument must be resolved in order to build the correct camera info topic.Added cv::waitkey(10) for blank popup Without the cv::waitkey(10), it results in a blank popup which crashes/ leads to a black popup. This change corrects that problem. ROS Kinetic, Ubuntu 16.04.3Fix CMake of image_transport/tutorial and polled_camera Fix loads of problems with the CMakeLists.image_transport/tutorial: Add dependency on generated msg Without this, build fails on Kinetic because ResizedImage.h has not been generated yet.image_transport/tutorial: Add missing catkin_INCLUDE_DIRS Without this, compilation files on Kinetic because ros.h cannot be found.1.11.11update changelogsfix linkage in tutorialsUse $catkin_EXPORTED_TARGETSimage_transport: fix CameraSubscriber shutdown (circular shared_ptr ref) CameraSubscriber uses a private boost::shared_ptr to share an impl object between copied instances. In CameraSubscriber::CameraSubscriber(), it handed this shared_ptr to boost::bind() and saved the created wall timer in the impl object, thus creating a circular reference. The impl object was therefore never freed. Fix that by passing a plain pointer to boost::bind().avoid a memory copy for the raw publisheradd a way to publish an image with only the data pointerMake function inline to avoid duplicated names when linking staticallyadd plugin examples for the tutorialupdate instructions for catkinremove uselessly linked library fixes#28add a tutorial for image_transportadd Jack as maintainerupdate my email addressfix the urlsuse the pluginlib script to remove some warningsadded license headers to various cpp and h filesget rid of the deprecated class_loader interfaceCMakeLists.txt clean upUpdated package.xml file(s) to handle new catkin buildtool_depend requirementadd the right link librariesIsolated plugins into their own library to follow new class_loader/pluginlib guidelines.remove the brief attributeadd xml filefix bad folder/librariesfix dependenciesadd catkin as a dependencycomply to the catkin APIinstall the include directoriesmake the libraries publiccatkinize for GroovyInitial image_common stack check-in, containing image_transport.Contributors: Aaditya Saraiya, Aaron Blasdel, Carl Delsey, Gary Servin, Jacob Perron, Jochen Sprickerhof, Karsten Knese, Lucas Walter, Martin Guenther, Martin Idel, Max Schwarz, Michael Carroll, Mikael Arguedas, Mirza Shah, Thibaud Chupin, Vincent Rabaud, William Woodall, gerkey, kwc, mihelich, mirzashah, pmihelich, straszheim, vrabaudinteractive_markersCleanup bsd 3 clause license usage (#61)Add missing includes (#81)Update maintainers (#79)Increase test timeout necessary for Connext (#77)Fix clang warnings (#75)Remove explicit template parameter inspin_until_future_complete(#72)Contributors: Bjar Ne, Dirk Thomas, Jacob Perron, Sarthak Mittal, Tully Footeintra_process_demoUpdate the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimokdl_parserRemove tinyxml dependency from kdl_parser. (#43)Remove unused find_library call (#40)Contributors: Chris Lalancette, Michael Carrolllaser_geometryUse rclcpp::Duration::from_seconds (#72)update maintainersincrease test timeoutContributors: Dirk Thomas, Ivan Santiago Paunovic, Jonathan Binney, Mabel ZhanglaunchOnly try to wrap the fd in a socket on Windows (#498)Close the socket pair used for signal management (#497)Remove is_winsock_handle() and instead test if wrapping the handle in a socket.socket() works (#494)Add frontend substitution for logging directory (#490)Add arg_choice arg to DeclareLaunchArguments (#483)Support Python 3.8-provided importlib.metadata (#482)Workaround asyncio signal handling on Unix (#479)Handle signals within the asyncio loop. (#476)Support non-interactive launch.LaunchService runs (#475)print stderr message when command failed (#474)Add frontend support for LogInfo action (#467)Validate unparsed attributes and subentities in launch_xml and launch_yaml (#468)Fix bug in launch.actions.TimerAction.parse() (#470)Allow configuring logging directory through environment variables (#460)Update package maintainers (#465)Expose Timer action in launch xml (#462)Fix dollar symbols in substitution grammar (#461)Add new conditions for checking launch configuration values (#453)Refactor launch service run_async loop to wait on futures and queued events (#449)Fix documentation typo (#446)Fix type_utils.extract_type() function. (#445)Handle empty strings in type coercion. (#443)Consolidate type_utils in a way that can be reused in substitution results that need to be coerced to a specific type (#438)Delete unnecessary loading of ‘launch.frontend.interpolate_substitution_method’ entry point that was never used (#434)Avoid side effect, defer until needed (#432)Remove pkg_resources, replace it with the use of the more modern importlib* libraries. (#430)Remove the asyncio.wait loop parameter. (#429)Add pytest.ini so local tests don’t display warning (#428)Defer shutdown if already running (#427)Add respawn and respawn_delay support (#426)Fix up parser.py (#414)Contributors: CHEN, Chris Lalancette, Christophe Bedard, Dan Rose, Dirk Thomas, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Michel Hidalgo, Scott K Logan, Takamasa Horibe, Victor Lopezlaunch_rosSupport Python 3.8 importlib.metadata, declare dependency (#229)Add options extensions to ros2launch and extensibility to the node action (#216)Make sure ParameterFile __del__ works without exception. (#212)Fix docblock in LoadComposableNodes (#207)Validate complex attributes of ‘node’ action (#198)Node.__init__() executable and ComposableNode.__init__() plugin arguments aren’t optional (#197)Remove constructors arguments deprecated since Foxy (#190)Make name and namespace mandatory in ComposableNodeContainer, remove deprecated alternatives (#189)Merge pull request#183from ros2/update-maintainers Update the package.xml files with the latest Open Robotics maintainersMove previous maintainer to Update the package.xml files with the latest Open Robotics maintainersFix AttributeError when accessing component container name (#177)Handle any substitution types for SetParameter name argument (#182)Asynchronously wait for load node service response (#174)Fix case where list of composable nodes is zero (#173)Do not use event handler for loading composable nodes (#170)Fix race with launch context changes when loading composable nodes (#166)Substitutions in parameter files (#168)Fix documentation typo (#167)Fix problems when parsing aCommandSubstitutionas a parameter value (#137)Add a way to set remapping rules for all nodes in the same scope (#163)Resolve libyaml warning when loading parameters from file (#161)Fix ComposableNode ignoring PushRosNamespace actions (#162)Add a SetParameter action that sets a parameter to all nodes in the same scope (#158)Make namespace parameter mandatory in LifecycleNode constructor (#157)Avoid using a wildcard to specify parameters if possible (#154)Fix no specified namespace (#153)Add pytest.ini so local tests don’t display warning (#152)Contributors: Chris Lalancette, Dereck Wonnacott, Geoffrey Biggs, Ivan Santiago Paunovic, Jacob Perron, Michael Jeronimo, Scott K Loganlaunch_testingUse unittest.mock instead of mock (#487)Update package maintainers (#465)Disable cleanup of test cases once they have been run (#406)Fix max() with empty sequence (#440)Use unittest.TestCase.id() for pytest failure reprs. (#436)Use unittest.TestCase.id() to put together jUnit XML output. (#435)Claim ownership (#433)Contributors: Dirk Thomas, Michel Hidalgo, Scott K Logan, William Woodalllaunch_testing_ament_cmakeUpdate package maintainers (#465)Add bsd license to launch due to files from roslaunch (#456)Use launch_test CMake target as output file basename (#448)Find Python debug interpreter on Windows (#437)Contributors: Dirk Thomas, Michel Hidalgo, William Woodalllaunch_testing_rosUse underscores in setup.cfg instead of dashes. (#227)Merge pull request#183from ros2/update-maintainersMove Pete to author, per clalancetteUpdate the package.xml files with the latest Open Robotics maintainersAdd pytest.ini so local tests don’t display warning (#152)Contributors: Chris Lalancette, Michael Jeronimo, Mike Purvislaunch_xmlAdd frontend support for LogInfo action (#467)Validate unparsed attributes and subentities in launch_xml and launch_yaml (#468)Add test for launch.actions.TimerAction (#470)Update package maintainers (#465)Use new type_utils functions (#438)Add pytest.ini so local tests don’t display warning (#428)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgolaunch_yamlAdd frontend support for LogInfo action (#467)Validate unparsed attributes and subentities in launch_xml and launch_yaml (#468)Update package maintainers (#465)Use new type_utils functions (#438)Close YAML file when we’re done. (#415)Add pytest.ini so local tests don’t display warning (#428)Contributors: Chris Lalancette, Dan Rose, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgolibcurl_vendorUpdate libcurl_vendor to the latest version (7.75.0). (#60)Add an override flag to force vendored build (#58)Update maintainers (#53)bump curl version to 7.68 (#47)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Dirk Thomas, Scott K Loganlibstatistics_collectorfix: measured values after the decimal point are truncated#79(#80)Update linter to run on rolling+focal (#81)Add automerge.yml config file (#70)Update QD to QL 1 (#68)Updated QD (#64)Updated QD Performance tests (#58)Added benchmark test to libstatistics_collector (#57) * Added benchmark test to libstatistics_collector * cppcheck supressed unknown macro warning - macos * Reset heap counters * Added feedback * Remove unknownMacro suppression from CMakeLists.txt * Added feedback * moved benchmark test to test/benchmark * Added feedback Co-authored-by: Devin Bonnie <47613035+dabonnie@users.noreply.github.com>Report failed workflows (#56) Allow codecov failures to be silentAdd default CODEOWNERS file (#55)Remove repo activity from individual repositories in favor of centralized reporting (#52)Don’t attempt to report if originating from a fork (#43)Removed doxygen warnings (#41) Co-authored-by: Anas Abou Allaban Add autoapprove action for dependabot (#40)Create Dependabot config file (#31) * Create Dependabot config file * Randomize time of run Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Prajakta Gokhale Updated QD to 3 (#30)Add Security Vulnerability Policy pointing to REP-2006. (#24) Co-authored-by: Emerson Knapp <537409+emersonknapp@users.noreply.github.com>Contributors: Alejandro Hernández Cordero, Chris Lalancette, Devin Bonnie, Emerson Knapp, Lucas Han, Prajakta Gokhale, Stephen Brawner, hsgwalibyaml_vendorupdating quality declaration links (re:ros2/docs.ros2.org#52) (#38)Update libyaml_vendor to 0.2.5. (#37)Fix linker flags for tests when CMake < 3.13 (#35)Always preserve source permissions in vendor packages (#31)Fix target_link_directories/link_directories in cmake (#29)Included benchmark tests (#20)Update Quality Declaration (#23)Update package maintainers. (#22)Bump QD to 3 and some minor style fixes (#19)Add Security Vulnerability Policy pointing to REP-2006. (#18)Add quality declaration libyaml_vendor (#12)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jorge Perez, Michel Hidalgo, Scott K Logan, shonigmannlifecycleCleanup the README.rst for the lifecycle demo. (#508)change ParameterEventHandler to take events as const ref instead of shared pointer (#494)Update the package.xml files with the latest Open Robotics maintainers (#466)Add missing required parameter in LifecycleNode launch action (#456)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Michael Jeronimo, William Woodalllifecycle_msgsChange index.ros.org -> docs.ros.org. (#122)Updating Quality Declaration (#120)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannlogging_demoUpdate logging macros (#476)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Audrow Nash, Michael Jeronimomap_msgsupdate maintainersContributors: Mabel Zhang, Steve Macenskimessage_filtersFind and export dependencies properly (#54)Add pytest.ini so local tests don’t display warning (#47)Contributors: Chris Lalancette, Michel Hidalgomimick_vendorAlways preserve source permissions in vendor packages (#19)Suppress update of pinned git repository (#17)Don’t overwrite -Wno-dev CMake argument (#18)Add missing build tool dependency on ‘git’ (#16)Update tag for armv7l support. (#15)Update tag for new cmake version requirement (#14)Export include directories (#13)Update package maintainers (#10)Suppress cppcheck for MMK_MANGLE_ (#8)Change Mimick tagged version. (#7)Change tag to pull latest Mimick version (#6)Pin Mimick version. (#5)Change imported dep to match ROS 2 fork (#4)Avoid CMAKE_BUILD_TYPE warnings on Windows. (#3)Remove dep tag + add maintainer(#2)Configure MSVC x64 builds when appropriate. (#1)First iteration vendor for Mimick libraryContributors: Jorge Perez, Michel Hidalgo, Scott K Logan, Stephen Brawner, brawnernav_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Add LoadMap service (#129)Update Quality levels to level 3 (#124)Finish up API documentation (#123)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, Steve Macenski, brawner, shonigmannosrf_pycommonFix osrf.py_common.process_utils.get_loop() implementation (#70)Python 2/3 version conflict (#69)remove jessie because we no longer support 3.4 (#67)Remove deprecated use of asyncio.coroutine decorator. (#64)Fix the __str__ method for windows terminal_color. (#65)Contributors: Chris Lalancette, Jochen Sprickerhof, Michel Hidalgo, William Woodallosrf_testing_tools_cpp[osrf_testing_tools_cpp] Add warnings (#54)Update cmake minimum version to 2.8.12 (#61)Add googletest v1.10.0 (#55)Workarounds for Android (#52) (#60)ChangeWIN32to__WIN32(#53)fix execinfo.h not found for QNX (#50)Contributors: Ahmed Sobhy, Audrow Nash, Dan Rose, Jacob Perron, Stephen Brawnerpendulum_controlReplace rmw_connext_cpp with rmw_connextdds (#489)Remove ineffective log output (#450) (#477)Update the package.xml files with the latest Open Robotics maintainers (#466)Remove deprecated warning (#459)Follow API/file name changes (ros2/realtime_support#94) (#451)Contributors: Anas Abou Allaban, Andrea Sorbini, Michael Jeronimo, y-okumura-isppendulum_msgsUpdate the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Michael Jeronimoperformance_test_fixtureRecord calls to calloc, update tests (#15)Make allocation counter atomic (#13) Even if the benchmark itself isn’t threaded, the process we’re testing could be. In any case, this should prevent those shenanigans from messing up the measurement.Add methods for pausing/resuming performance metrics (#10) * Add methods for pausing/resuming performance metricsAdd benchmarks to evaluate overhead (#11) * Add benchmarks to evaluate overhead in performance testsAdd namespace performance_test_fixture to .cpp (#9)Export dependency on benchmark and osrf_testing_tools_cpp (#8)Update maintainers (#7)Expose a function for resetting the heap counters (#6)Stop recording memory operations sooner (#5)Suppress memory tools warning if tests will be skipped (#4)Export dependency on ament_cmake_google_benchmark (#3)Add missing dependency on ament_cmake_google_benchmark (#2)Initial ‘performance_test_fixture’ package (#1)Initial commitContributors: Alejandro Hernández Cordero, Scott K Logan, brawnerpluginlibUse rcpputils for the filesystem implementation. (#212)Check for NULL in XMLElement::AttributeCheck for NULL in XMLElement::GetTextCheck for NULL in XMLNode::ValueRemove unused variable output_library (#211)Make Chris a maintainer of pluginlib. (#210)Add QNX C++ fs library compiler option (#205)Fix cmake 3.5 compatibility (#203)Add function for same-package pluginlib tests (#201)Remove deprecated boost functions (#199)Contributors: Ahmed Sobhy, Chris Lalancette, Jeremie Deray, Karsten Knese, Shane Loretzpybind11_vendorUpdate maintainers (#7)Merge pull request#3from ros2/fix_windows_warningremove passing in CMAKE_BUILD_TYPE Signed-off-by: Mabel Zhang cleanup Signed-off-by: Mabel Zhang do not define CMAKE_BUILD_TYPE on windows Signed-off-by: Mabel Zhang suppress all developer warnings Signed-off-by: Mabel Zhang suppress warning on windows Signed-off-by: Mabel Zhang attempt to fix windows warning Signed-off-by: Mabel Zhang Disable building pybind11 tests (#1) Signed-off-by: Karsten Knese Update to pybind 2.5.0 (#2) Signed-off-by: Mabel Zhang Create pybind11 vendor package. Signed-off-by: Michael Carroll Contributors: Karsten Knese, Mabel Zhang, Michael Carroll, Shane Loretzpython_cmake_moduleUpdate maintainers (#2)Contributors: Shane Loretzpython_qt_bindingAdd repo READMEShorten some long lines of CMake (#99)Update maintainers (#96) (#98)Add pytest.ini so local tests don’t display warning (#93)Contributors: Chris Lalancette, Scott K Logan, Shane Loretzqt_dotgraphadd API to set edge tooltip (#237)qt_guiAlways prefer ‘Tango’ icon theme (#250)Fix ‘dict_keys’ object not subscriptable (#243)allow hide title in standalone (#235)add logic to load qt_gui_icons on windows and macOS (#222)fix exporting perspective for Python 3.6 (#228)remove tango-icon-theme dependency (#224)Contributors: Michael Jeronimo, Scott K Loganqt_gui_cppFix duplicated QMap to QMultiMap (#244)Switch to using the filesystem implementation in rcpputils. (#239)avoid a warning about C++ plugins on Windows (#232)qt_gui_cpp_sip: declare private assignment operator for SIP (#226)Contributors: Chris Lalancette, Homalozoa Xquality_of_service_demo_cppAdd demo of how to use qos overrides (#474)Update the package.xml files with the latest Open Robotics maintainers (#466)Update comments in quality_of_service_demo_cpp message_lost_talker and message_lost_listener (#458)Add message lost status event demo using rclcpp (#453)Contributors: Ivan Santiago Paunovic, Michael Jeronimoquality_of_service_demo_pyUse underscores instead of dashes in setup.cfg (#502)QoS overrides demo in python (#479)Update deprecated qos policy value names (#468)Update the package.xml files with the latest Open Robotics maintainers (#466)Add rclpy message lost status event demo (#457)Contributors: Ivan Santiago Paunovic, Michael JeronimorclFix up test_network_flow_endpoints. (#912)Make test_two_timers_ready_before_timeout less flaky (#911)Add publishing instrumentation (#905)Unique network flows (#880)updating quality declaration links (re:ros2/docs.ros2.org#52) (#909)Add functions for waiting for publishers and subscribers (#907)Revert “Mark cyclonedds test_service test as flakey (#648)” (#904)Guard against returning NULL or empty node names (#570)Remove exceptions for rmw_connext_cpp tests. (#903)Add support for rmw_connextdds (#895)Put an argument list of ‘void’ where no arguments are expected. (#899)Cleanup documentation for doxygen. (#896)Reference test resources directly from source tree (#554)Re-add “Improve trigger test for graph guard condition (#811)” (#884)Revert “Improve trigger test for graph guard condition (#811)” (#883)Move the guard condition cleanup after removing callback. (#877)Make test_subscription_nominal_string_sequence more reliable (#881)Improve trigger test for graph guard condition (#811)Add NULL check in remap.c (#879)Add const to constant rcl_context functions (#872)Fix another failing test on CentOS 7 (#863)Update QDs to QL 1 (#866)Address clang static analysis issues (#865)Fix flaky test_info_by_topic (#859)Update QL (#858)Refactor for removing unnecessary source code (#857)Clarify storing of current_time (#850)Make tests in test_graph.cpp more reliable (#854)Fix for external log segfault after SIGINT (#844)Update tracetools QL and add to rcl_lifecycle’s QD (#845)Make test logging rosout more reliable (#846)Return OK when finalizing zero-initialized contexts (#842)Zero initialize events an size_of_events members of rcl_wait_set_t (#841)Update deprecated gtest macros (#818)Make sure to check the return value of rcl APIs. (#838)Add convenient node method to get a final topic/service name (#835)Remove redundant error formatting (#834)Fix memory leak in rcl_subscription_init()/rcl_publisher_init() (#794)Update maintainers (#825)Add a semicolon to RCUTILS_LOGGING_AUTOINIT. (#816)Improve error messages in rcl_lifecycle (#742)Fix memory leak on serialized message in test_publisher/subscription.cpp (#801)Fix memory leak because of mock test (#800)Spelling correction (#798)Fix that not to deallocate event impl in some failure case (#790)calling fini functions to avoid memory leak (#791)Bump rcl arguments’ API test coverage (#777)Fix rcl arguments’ API memory leaks and bugs (#778)Add coverage tests wait module (#769)Fix wait set allocation cleanup (#770)Improve test coverage in rcl (#764)Check if rcutils_strdup() outcome immediately (#768)Cleanup rcl_get_secure_root() implementation (#762)Add fault injection macros to rcl functions (#727)Yield rcl_context_fini() error codes (#763)Do not invalidate context before successful shutdown (#761)Zero initialize guard condition on failed init (#760)Adding tests to arguments API (#752)Extend rcl_expand_topic_name() API test coverage (#758)Add coverage tests 94% to service API (#756)Clean up rcl_expand_topic_name() implementation (#757)Complete rcl enclave validation API coverage (#751)Cope with base function restrictions in mocks (#753)Fix allocation when copying arguments (#748)Complete rcl package’s logging API test coverage (#747)Improve coverage to 95% in domain id, init option, rmw implementation id and log level modules (#744)Fix rcl package’s logging API error code documentation and handling (#746)Fix bug error handling in get_param_files (#743)Complete subscription API test coverage (#734)increase timeouts in test_services fixtures for Connext (#745)Tweaks to client.c and subscription.c for cleaner init/fini (#728)Improve error checking and handling in subscription APIs (#739)Add deallocate calls to free strdup allocated memory (#737)Add missing calls to rcl_convert_rmw_ret_to_rcl_ret (#738)Add mock tests, publisher 95% coverage (#732)Restore env variables set in the test_failing_configuration. (#733)Expose qos setting for /rosout (#722)Reformat rmw_impl_id_check to call a testable function (#725)Add extra check for invalid event implementation (#726)Consolidate macro duplication (#653)Add test for subscription message lost event (#705)Add function rcl_event_is_valid (#720)Move actual domain id from node to context (#718)Removed doxygen warnings (#712)Remove some dead code.Make sure to call rcl_arguments_fini at the end of the test.Add remap needed null check (#711)Make public init/fini rosout publisher (#704)Move rcl_remap_copy to public header (#709)Implement a generic way to change logging levels (#664)Remove domain_id and localhost_only from node_options (#708)Add coverage tests (#703)Add bad arguments tests for coverage (#698)Remove unused internal prototypes (#699)Update quality declaration and coverage (#674)Add setter and getter for domain_id in rcl_init_options_t (#678)Remove unused pytest dependency from rcl. (#695)Fix link to latest API docs (#692)Keep domain id if ROS_DOMAIN_ID is invalid. (#689)Remove unused check context.c (#691)Add check rcl_node_options_copy invalid out (#671)Update tracetools’ QL to 2 in rcl’s QD (#690)Improve subscription coverage (#681)Improve rcl timer test coverage (#680)Improve wait sets test coverage (#683)Improve rcl init test coverage. (#684)Improve clock test coverage. (#685)Add message lost event (#673)Minor fixes to rcl clock implementation. (#688)Improve enclave validation test coverage. (#682)Use RCL_RET_* codes only. (#686)Fixed doxygen warnings (#677)Add tests for rcl package (#668)Remove logging_external_interface.h, provided by rcl_logging_interface package now (#676)Print RCL_LOCALHOST_ENV_VAR if error happens via rcutils_get_env. (#672)Contributors: Ada-King, Alejandro Hernández Cordero, Ananya Muddukrishna, Andrea Sorbini, Audrow Nash, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Dan Rose, Dirk Thomas, Geoffrey Biggs, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Lei Liu, Michel Hidalgo, Nikolai Morin, Scott K Logan, Stephen Brawner, Thijs Raymakers, brawner, shonigmann, tomoyarcl_actionupdating quality declaration links (re:ros2/docs.ros2.org#52) (#909)Don’t expect RCL_RET_TIMEOUT to set an error string (#900)Add support for rmw_connextdds (#895)Avoid setting error message twice. (#887)Address various clang static analysis fixes (#864)Update QDs to QL 1 (#866)Update QL (#858)Make sure to always check return values (#840)Update deprecated gtest macros (#818)Make sure to check the return value of rcl APIs. (#838)Update maintainers (#825)Store reference to rcl_clock_t instead of copy (#797)Use valid clock in case of issue in rcl_timer_init (#795)Add fault injection macros and unit tests to rcl_action (#730)Change some EXPECT_EQ to ASSERT_EQ in test_action_server. (#759)Removed doxygen warnings (#712)Address issue 716 by zero initializing pointers and freeing memory (#717)Update quality declaration and coverage (#674)Fixed doxygen warnings (#677)Contributors: Alejandro Hernández Cordero, Andrea Sorbini, Audrow Nash, Chen Lihui, Chris Lalancette, Ivan Santiago Paunovic, Shane Loretz, Stephen Brawner, brawner, shonigmannrcl_interfacesChange index.ros.org -> docs.ros.org. (#122)Updating Quality Declaration (#120)Add field to the parameter description to specify dynamic/static typing. (#118)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Michel Hidalgo, Stephen Brawner, brawner, shonigmannrcl_lifecycleupdating quality declaration links (re:ros2/docs.ros2.org#52) (#909)make rcl_lifecycle_com_interface optional in lifecycle nodes (#882)Update QDs to QL 1 (#866)Update QL (#858)Make sure to always check return values (#840)Update tracetools QL and add to rcl_lifecycle’s QD (#845)Add compiler warnings (#830)Make sure to check the return value of rcl APIs. (#838)Add lifecycle node state transition instrumentation (#804)Update maintainers (#825)Improve error messages in rcl_lifecycle (#742)Fix test_rcl_lifecycle (#788)Add fault injection macros and unit tests to rcl_lifecycle (#731)Remove std::cout line from test_rcl_lifecycle.cpp (#773)Set transition_map->states/transition size to 0 on fini (#729)Topic fix rcl lifecycle test issue (#715)Removed doxygen warnings (#712)Update quality declaration and coverage (#674)Contributors: Alejandro Hernández Cordero, Audrow Nash, Barry Xu, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Karsten Knese, Lei Liu, Stephen Brawner, brawner, shonigmannrcl_logging_interfaceUpdate QD to QL 1 (#66)Use rcutils_expand_user in rcl_logging_get_logging_directory (#59)Allow configuring logging directory through environment variables (#53)Update the maintainers. (#55)Add new package with rcl logging interface (#41)Contributors: Chris Lalancette, Christophe Bedard, Stephen Brawnerrcl_logging_log4cxxAllow configuring logging directory through environment variables (#53)Update the maintainers. (#55)Remove unused pytest dependency. (#43)Use new package with rcl logging interface (#41)Contributors: Chris Lalancette, Christophe Bedardrcl_logging_noopMake internal dependencies private (#60)Update the maintainers. (#55)Remove unused pytest dependency. (#43)Use new package with rcl logging interface (#41)Contributors: Chris Lalancette, Shane Loretzrcl_logging_spdlogupdating quality declaration links (re:ros2/docs.ros2.org#52) (#73)Include what you use (#71)Update QD to QL 1 (#66)Make sure to check return value from external_initialize. (#65)updated QD section 3.i and 3ii and spelling error (#63)rcl_logging_spdlog: Increased QL to 2 in QDUpdated spdlog QL in QDMake internal dependencies private (#60)[rcl_logging_spdlog] Add warnings (#54)Allow configuring logging directory through environment variables (#53)Update the maintainers. (#55)Added benchmark test to rcl_logging_spdlog (#52)Used current_path() function from rcpputils (#51)Add fault injection unittest to increase coverage (#49)Bump QD to level 3 and updated QD (#44)Added Doxyfile and fixed related warnings (#42)Use new package with rcl logging interface (#41)Increased test coverage (#40)Add Security Vulnerability Policy pointing to REP-2006.Rename Quality_Declaration.md -> QUALITY_DECLARATION.mdContributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Scott K Logan, Shane Loretz, Stephen Brawner, ahcorde, brawner, shonigmannrcl_yaml_param_parserupdating quality declaration links (re:ros2/docs.ros2.org#52) (#909)Enable compiler warnings (#831)Update QDs to QL 1 (#866)Rearrange test logic to avoid reference to null (#862)Update QL (#858)Make sure to initialize the end_mark for yaml_event_t (#849)Check for valid node names in parameters files (#809)Update maintainers (#825)Updated performance section QD (#817)Several memory-related fixes for rcl_variant_t benchmarks (#813)Improved rcl_yaml_param_parser benchmark test (#810)Added benchmark test to rcl_yaml_param_parser (#803)Remove MAX_NUM_PARAMS_PER_NODE and MAX_NUM_NODE_ENTRIES limitation. (#802)Add mocking unit tests for rcl_yaml_param_parser (coverage part 3/3) (#772)Add fault-injection unit tests (coverage part 2/3) (#766)Add basic unit tests for refactored functions in rcl_yaml_param_parser (coverage part 1/3) (#771)Fix yaml parser error when meets .nan (refactor on#754) (#781)Refactor parser.c for better testability (#754)Don’t overwrite cur_ns pointer if reallocation fails (#780)Fix mem leaks in unit test from 776 (#779)Fix rcl_parse_yaml_file() error handling. (#776)Don’t overwrite string_array pointer on reallocation failure (#775)Set yaml_variant values to NULL on finalization (#765)Remove debugging statements. (#755)Removed doxygen warnings (#712)Update quality declaration and coverage (#674)Contributors: Alejandro Hernández Cordero, Audrow Nash, Chen Lihui, Chris Lalancette, Ivan Santiago Paunovic, Michel Hidalgo, Scott K Logan, Stephen Brawner, brawner, shonigmann, tomoyarclcppUse OnShutdown callback handle instead of OnShutdown callback (#1639) (#1650)use dynamic_pointer_cast to detect allocator mismatch in intra process manager (#1643) (#1644)Increase cppcheck timeout to 500s (#1634)Clarify node parameters docs (#1631)Avoid returning loan when none was obtained. (#1629)Use a different implementation of mutex two priorities (#1628)Do not test the value of the history policy when testing the get_publishers/subscriptions_info_by_topic() methods (#1626)Check first parameter type and range before calling the user validation callbacks (#1627)Restore test exception for Connext (#1625)Fix race condition in TimeSource clock thread setup (#1623)remove deprecated code which was deprecated in foxy and should be removed in galactic (#1622)Change index.ros.org -> docs.ros.org. (#1620)Unique network flows (#1496)Add spin_some support to the StaticSingleThreadedExecutor (#1338)Add publishing instrumentation (#1600)Create load_parameters and delete_parameters methods (#1596)refactor AnySubscriptionCallback and add/deprecate callback signatures (#1598)Add generic publisher and generic subscription for serialized messages (#1452)use context fromnode_base\_for clock executor. (#1617)updating quality declaration links (re:ros2/docs.ros2.org#52) (#1615)Initialize integers in test_parameter_event_handler.cpp to avoid undefined behavior (#1609)Namespace tracetools C++ functions (#1608)Revert “Namespace tracetools C++ functions (#1603)” (#1607)Namespace tracetools C++ functions (#1603)Clock subscription callback group spins in its own thread (#1556)Remove rmw_connext_cpp references. (#1595)Add API for checking QoS profile compatibility (#1554)Document misuse of parameters callback (#1590)use const auto & to iterate over parameters (#1593)Guard against integer overflow in duration conversion (#1584)get_parameters service should return empty if undeclared parameters are allowed (#1514)Made ‘Context::shutdown_reason’ function a const function (#1578)Document design decisions that were made for statically typed parameters (#1568)Fix doc typo in CallbackGroup constructor (#1582)Enable qos parameter overrides for the /parameter_events topic (#1532)Add support for rmw_connextdds (#1574)Remove ‘struct’ from the rcl_time_jump_t. (#1577)Add tests for declaring statically typed parameters when undeclared parameters are allowed (#1575)Quiet clang memory leak warning on “DoNotOptimize”. (#1571)Add ParameterEventsSubscriber class (#829)When a parameter change is rejected, the parameters map shouldn’t be updated. (#1567)Fix when to throw the NoParameterOverrideProvided exception. (#1567)Fix SEGV caused by order of destruction of Node sub-interfaces (#1469)Fix benchmark test failure introduced in#1522(#1564)Fix documented example in create_publisher (#1558)Enforce static parameter types (#1522)Allow timers to keep up the intended rate in MultiThreadedExecutor (#1516)Fix UBSAN warnings in any_subscription_callback. (#1551)Fix runtime error: reference binding to null pointer of type (#1547)Reference test resources directly from source tree (#1543)clear statistics after window reset (#1531) (#1535)Fix a minor string error in the topic_statistics test. (#1541)AvoidResourcedeadlockavoidedif use intra_process_comms (#1530)Avoid an object copy in parameter_value.cpp. (#1538)Assert that the publisher_list size is 1. (#1537)Don’t access objects after they have been std::move (#1536)Update for checking correct variable (#1534)Destroy msg extracted from LoanedMessage. (#1305)Add instrumentation for linking a timer to a node (#1500)Fix error when using IPC with StaticSingleThreadExecutor (#1520)Change to using unique_ptrs for DummyExecutor. (#1517)Allow reconfiguring ‘clock’ topic qos (#1512)Allow to add/remove nodes thread safely in rclcpp::Executor (#1505)Call rclcpp::shutdown in test_node for clean shutdown on Windows (#1515)Reapply “Add get_logging_directory method to rclcpp::Logger (#1509)” (#1513)use describe_parameters of parameter client for test (#1499)Revert “Add get_logging_directory method to rclcpp::Logger (#1509)” (#1511)Add get_logging_directory method to rclcpp::Logger (#1509)Better documentation for the QoS class (#1508)Modify excluding callback duration from topic statistics (#1492)Make the test of graph users more robust. (#1504)Make sure to wait for graph change events in test_node_graph. (#1503)add timeout to SyncParametersClient methods (#1493)Fix wrong test expectations (#1497)Update create_publisher/subscription documentation, clarifying when a parameters interface is required (#1494)Fix string literal warnings (#1442)support describe_parameters methods to parameter client. (#1453)Add getters to rclcpp::qos and rclcpp::Policy enum classes (#1467)Change nullptr checks to use ASSERT_TRUE. (#1486)Adjust logic around finding and erasing guard_condition (#1474)Update QDs to QL 1 (#1477)Add performance tests for parameter transport (#1463)Move ownership of shutdown_guard_condition to executors/graph_listener (#1404)Add options to automatically declare qos parameters when creating a publisher/subscription (#1465)Addtake_datatoWaitableanddatatoAnyExecutable(#1241)Add benchmarks for node parameters interface (#1444)Remove allocation from executor::remove_node() (#1448)Fix test crashes on CentOS 7 (#1449)Bump rclcpp packages to Quality Level 2 (#1445)Added executor benchmark tests (#1413)Add fully-qualified namespace to WeakCallbackGroupsToNodesMap (#1435)Deprecate Duration(rcl_duration_value_t) in favor of static Duration::from_nanoseconds(rcl_duration_value_t) (#1432)Avoid parsing arguments twice inrclcpp::init_and_remove_ros_arguments(#1415)Add service and client benchmarks (#1425)Set CMakeLists to only use default rmw for benchmarks (#1427)Update tracetools’ QL in rclcpp’s QD (#1428)Add missing locking to the rclcpp_action::ServerBase. (#1421)Initial benchmark tests for rclcpp::init/shutdown create/destroy node (#1411)Refactor test CMakeLists in prep for benchmarks (#1422)Add methods in topic and service interface to resolve a name (#1410)Update deprecated gtest macros (#1370)Clear members for StaticExecutorEntitiesCollector to avoid shared_ptr dependency (#1303)Increase test timeouts of slow running tests with rmw_connext_cpp (#1400)Avoid self dependency that not destoryed (#1301)Update maintainers (#1384)Add clock qos to node options (#1375)Fix NodeOptions copy constructor (#1376)Make sure to clean the external client/service handle. (#1296)Increase coverage of WaitSetTemplate (#1368)Increase coverage of guard_condition.cpp to 100% (#1369)Add coverage statement (#1367)Tests for LoanedMessage with mocked loaned message publisher (#1366)Add unit tests for qos and qos_event files (#1352)Finish coverage of publisher API (#1365)Finish API coverage on executors. (#1364)Add test for ParameterService (#1355)Add time API coverage tests (#1347)Add timer coverage tests (#1363)Add in additional tests for parameter_client.cpp coverage.Minor fixes to the parameter_service.cpp file.reset rcl_context shared_ptr after calling rcl_init sucessfully (#1357)Improved test publisher - zero qos history depth value exception (#1360)Covered resolve_use_intra_process (#1359)Improve test_subscription_options (#1358)Add in more tests for init_options coverage. (#1353)Test the remaining node public API (#1342)Complete coverage of Parameter and ParameterValue API (#1344)Add in more tests for the utilities. (#1349)Add in two more tests for expand_topic_or_service_name. (#1350)Add tests for node_options API (#1343)Add in more coverage for expand_topic_or_service_name. (#1346)Test exception in spin_until_future_complete. (#1345)Add coverage tests graph_listener (#1330)Add in unit tests for the Executor class.Allow mimick patching of methods with up to 9 arguments.Improve the error messages in the Executor class.Add coverage for client API (#1329)Increase service coverage (#1332)Make more of the static entity collector API private.Const-ify more of the static executor.Add more tests for the static single threaded executor.Many more tests for the static_executor_entities_collector.Get one more line of code coverage in memory_strategy.cppBugfix when adding callback group.Fix typos in comments.Remove deprecated executor::FutureReturnCode APIs. (#1327)Increase coverage of publisher/subscription API (#1325)Not finalize guard condition while destructing SubscriptionIntraProcess (#1307)Expose qos setting for /rosout (#1247)Add coverage for missing API (except executors) (#1326)Include topic name in QoS mismatch warning messages (#1286)Add coverage tests context functions (#1321)Increase coverage of node_interfaces, including with mocking rcl errors (#1322)Make node_graph::count_graph_users() const (#1320)Add coverage for wait_set_policies (#1316)Only exchange intra_process waitable if nonnull (#1317)Check waitable for nullptr during constructor (#1315)Call vector.erase with end iterator overload (#1314)Use best effort, keep last, history depth 1 QoS Profile for ‘/clock’ subscriptions (#1312)Add tests type_support module (#1308)Replace std_msgs with test_msgs in executors test (#1310)Add set_level for rclcpp::Logger (#1284)Remove unused private function (rclcpp::Node and rclcpp_lifecycle::Node) (#1294)Adding tests basic getters (#1291)Adding callback groups in executor (#1218)Refactor Subscription Topic Statistics Tests (#1281)Add operator!= for duration (#1236)Fix clock thread issue (#1266) (#1267)Fix topic stats test, wait for more messages, only check the ones with samples (#1274)Add get_domain_id method to rclcpp::Context (#1271)Fixes for unit tests that fail under cyclonedds (#1270)initialize_logging_ should be copied (#1272)Use static_cast instead of C-style cast for instrumentation (#1263)Make parameter clients use template constructors (#1249)Ability to configure domain_id via InitOptions. (#1165)Simplify and fix allocator memory strategy unit test for connext (#1252)Use global namespace for parameter events subscription topic (#1257)Increase timeouts for connext for long tests (#1253)Adjust test_static_executor_entities_collector for rmw_connext_cpp (#1251)Fix failing test with Connext since it doesn’t wait for discovery (#1246)Fix node graph test with Connext and CycloneDDS returning actual data (#1245)Warn about unused result of add_on_set_parameters_callback (#1238)Unittests for memory strategy files, except allocator_memory_strategy (#1189)EXPECT_THROW_EQ and ASSERT_THROW_EQ macros for unittests (#1232)Add unit test for static_executor_entities_collector (#1221)Parameterize test executors for all executor types (#1222)Unit tests for allocator_memory_strategy.cpp part 2 (#1198)Unit tests for allocator_memory_strategy.hpp (#1197)Derive and throw exception in spin_some spin_all for StaticSingleThreadedExecutor (#1220)Make ring buffer thread-safe (#1213)Add missing RCLCPP_PUBLIC to ~StaticExecutorEntitiesCollector (#1227)Document graph functions don’t apply remap rules (#1225)Remove recreation of entities_collector (#1217)Fix rclcpp::NodeOptions::operator= (#1211)Link against thread library where necessary (#1210)Unit tests for node interfaces (#1202)Remove usage of domain id in node options (#1205)Remove deprecated set_on_parameters_set_callback function (#1199)Fix conversion of negative durations to messages (#1188)Fix implementation of NodeOptions::use_global_arguments() (#1176)Bump to QD to level 3 and fixed links (#1158)Fix pub/sub count API tests (#1203)Update tracetools’ QL to 2 in rclcpp’s QD (#1187)Fix exception message on rcl_clock_init (#1182)Throw exception if rcl_timer_init fails (#1179)Unit tests for some header-only functions/classes (#1181)Callback should be perfectly-forwarded (#1183)Add unit tests for logging functionality (#1184)Add create_publisher include to create_subscription (#1180)Check period duration in create_wall_timer (#1178)Fix get_node_time_source_interface() docstring (#988)Add message lost subscription event (#1164)Add spin_all method to Executor (#1156)Reorganize test directory and split CMakeLists.txt (#1173)Check if context is valid when looping in spin_some (#1167)Add check for invalid topic statistics publish period (#1151)Fix spin_until_future_complete: check spinning value (#1023)Fix doxygen warnings (#1163)Fix reference to rclcpp in its Quality declaration (#1161)Allow spin_until_future_complete to accept any future like object (#1113)Contributors: Ada-King, Alejandro Hernández Cordero, Ananya Muddukrishna, Andrea Sorbini, Audrow Nash, Barry Xu, BriceRenaudeau, Chen Lihui, Chris Lalancette, Christophe Bedard, Claire Wang, Colin MacKenzie, Daisuke Sato, Devin Bonnie, Dirk Thomas, DongheeYe, Ivan Santiago Paunovic, Jacob Perron, Jannik Abbenseth, Johannes Meyer, Jorge Perez, Karsten Knese, Louise Poubel, Miaofei Mei, Michel Hidalgo, Miguel Company, Morgan Quigley, Nikolai Morin, Pedro Pena, Sarthak Mittal, Scott K Logan, Shane Loretz, Stephen Brawner, Steven! Ragnarök, Tomoya Fujita, William Woodall, anaelle-sw, bpwilcox, brawner, eboasson, hsgwa, mauropasse, shonigmann, suab321321, tomoyarclcpp_actionReturns CancelResponse::REJECT while goal handle failed to transit to CANCELING state (#1641) (#1653)Fix action server deadlock issue that caused by other mutexes locked in CancelCallback (#1635) (#1646)updating quality declaration links (re:ros2/docs.ros2.org#52) (#1615)Add support for rmw_connextdds (#1574)node_handle must be destroyed after client_handle to prevent memory leak (#1562)Finalize rcl_handle to prevent leak (#1528) (#1529)Fix#1526. (#1527)Fix action server deadlock (#1285) (#1313)Goal response callback compatibility shim with deprecation of old signature (#1495)[rclcpp_action] Add warnings (#1405)Update QDs to QL 1 (#1477)Addtake_datatoWaitableanddatatoAnyExecutable(#1241)Fix test crashes on CentOS 7 (#1449)Bump rclcpp packages to Quality Level 2 (#1445)Add rclcpp_action action_server benchmarks (#1433)Benchmark rclcpp_action action_client (#1429)Add missing locking to the rclcpp_action::ServerBase. (#1421)Increase test timeouts of slow running tests with rmw_connext_cpp (#1400)Update maintainers (#1384)Increase coverage rclcpp_action to 95% (#1290)Pass goal handle to goal response callback instead of a future (#1311)Remove deprecated client goal handle method for getting result (#1309)Increase test timeout necessary for Connext (#1256)Bump to QD to level 3 and fixed links (#1158)Add rcl_action_client_options when creating action client. (#1133)Fix doxygen warnings (#1163)Increase rclcpp_action test coverage (#1153)Contributors: Alejandro Hernández Cordero, Andrea Sorbini, Audrow Nash, Chris Lalancette, Daisuke Sato, Dirk Thomas, Ivan Santiago Paunovic, Jacob Perron, Kaven Yau, Louise Poubel, Michel Hidalgo, Stephen Brawner, Tomoya Fujita, William Woodall, brawner, shonigmann, tomoya, y-okumura-isprclcpp_componentsupdating quality declaration links (re:ros2/docs.ros2.org#52) (#1615)Use std compliant non-method std::filesystem::exists function (#1502)Fix string literal warnings (#1442)Update QDs to QL 1 (#1477)Add benchmarks for components (#1476)Bump rclcpp packages to Quality Level 2 (#1445)Update maintainers (#1384)ComponentManager: switch off parameter services and event publisher (#1333)Bump to QD to level 3 and fixed links (#1158)Include original exception in ComponentManagerException (#1157)Contributors: Alejandro Hernández Cordero, Audrow Nash, Ivan Santiago Paunovic, Josh Langsfeld, Louise Poubel, Martijn Buijs, Scott K Logan, Stephen Brawner, Tomoya Fujita, shonigmannrclcpp_lifecycleAdd generic publisher and generic subscription for serialized messages (#1452)updating quality declaration links (re:ros2/docs.ros2.org#52) (#1615)Fix flaky lifecycle node tests (#1606)Clock subscription callback group spins in its own thread (#1556)Delete debug messages (#1602)add automatically_add_executor_with_node option (#1594)make rcl_lifecyle_com_interface optional in lifecycle nodes (#1507)Add support for rmw_connextdds (#1574)Fix SEGV caused by order of destruction of Node sub-interfaces (#1469)Enforce static parameter types (#1522)add LifecycleNode::get_transition_graph to match services. (#1472)Update QDs to QL 1 (#1477)Benchmark lifecycle features (#1462)Reserve vector capacities and use emplace_back for constructing vectors (#1464)[rclcpp_lifecycle] Change uint8_t iterator variables to size_t (#1461)Bump rclcpp packages to Quality Level 2 (#1445)Increase test timeouts of slow running tests with rmw_connext_cpp (#1400)Update maintainers (#1384)Add clock qos to node options (#1375)Increase test coverage of rclcpp_lifecycle to 96% (#1298)Log error instead of throwing exception in Transition and State reset(), mark no except (#1297)Remove unused private function (rclcpp::Node and rclcpp_lifecycle::Node) (#1294)Remove rmw-dependent unit-test checks (#1293)Added missing tests for rclcpp lifecycle (#1240)Warn about unused result of add_on_set_parameters_callback (#1238)Remove deprecated set_on_parameters_set_callback function (#1199)Bump to QD to level 3 and fixed links (#1158)Fix race in test_lifecycle_service_client (#1204)Fix doxygen warnings (#1163)Contributors: Alejandro Hernández Cordero, Andrea Sorbini, BriceRenaudeau, Claire Wang, Colin MacKenzie, Dirk Thomas, Ivan Santiago Paunovic, Jacob Perron, Karsten Knese, Louise Poubel, Nikolai Morin, Stephen Brawner, anaelle-sw, brawner, shonigmann, tomoyarclpyBreak log function execution ASAP if configured severity is too high (#776) (#783)typo fix. (#768)Restore exceptions for Connext and message timestamps on Windows (#765)Use correct type when creating test publisher (#764)Add a test for destroy_node while spinning (#663)Add __enter__ and __exit__ to Waitable (#761)Check if shutdown callback weak method is valid before calling it (#754)Change index.ros.org -> docs.ros.org. (#755)Use py::class_ for rcl_event_t (#750)Convert Clock to use a C++ Class (#749)Convert Service to use C++ Class (#747)Fix windows warning by using consistent types (#753)Use py::class_ for rmw_service_info_t and rmw_request_id_t (#748)Convert Timer to use a C++ Class (#745)Add PythonAllocator (#746)Use py::class_ for rmw_qos_profile_t (#741)Combine pybind11 modules into one (#743)Use py::class_ for rcl_duration_t (#744)Fix bug in unique_ptr type argument (#742)Convert Client to use C++ Class (#739)Converting last of _rclpy.c to pybind11 (#738)Make sure only non-empty std::vector of arguments are indexed (#740)Use py::class_ for rcl_time_point_t (#737)Convert logging mutex functions to pybind11 (#735)Document misuse of of parameter callbacks (#734)Convert QoS APIs to pybind11 (#736)Add API for checking QoS profile compatibility (#708)Replace rmw_connext_cpp with rmw_connextdds (#698)Convert last of pub/sub getters to pybind11 (#733)Pybind 11: count_subscribers and count_publishers (#732)Convert more node accessors to pybind11 (#730)Pybind11-ify rclpy_get_node_parameters (#718)Modify parameter service behavior when allow_undeclared_parameters is false and the requested parameter doesn’t exist (#661)Include pybind11 first to fix windows debug warning (#731)Convert init/shutdown to pybind11 (#715)Convert take API to pybind11 (#721)Migrate qos event APIs to pybind11 (#723)Remove pybind11 from rclpy common (#727)Look up pybind11 package once (#726)typo fix. (#729)[pybind11] Node Accessors (#719)Convert serialize/deserialize to pybind11 (#712)Convert names_and_types graph APIs to pybind11 (#717)Use Pybind11 for name functions (#709)Better checks for valid msg and srv types (#714)Convert duration to pybind11 (#716)Convert wait_set functions to pybind11 (#706)Explicitly populate tuple with None (#711)Change the time jump time type to just rcl_time_jump_t. (#707)Convert rclpy service functions to pybind11 (#703)Bump the cppcheck timeout by 2 minutes (#705)Convert subscription functions to pybind11 (#696)Convert rclpy client functions to pybind11 (#701)Fix static typing when allow undeclared (#702)Convert publisher functions to pybind11 (#695)Convert clock and time functions to pybind11 (#699)Set destructor on QoS Profile struct (#700)Convert timer functions to pybind11 (#693)Convert guard conditions functions to pybind11 (#692)Convert service info functions to pybind11 (#694)Enforce static parameter types when dynamic typing is not specified (#683)rclpy_ok and rclpy_create_context to pybind11 (#691)Include Pybind11 before Python.h (#690)Clean up exceptions in _rclpy_action (#685)Clean windows flags on _rclpy_pybind11 and _rclpy_action (#688)Use pybind11 for _rclpy_handle (#668)Split rclpy module for easier porting to pybind11 (#675)Use Pybind11 to generate _rclpy_logging (#659)Copy windows debug fixes for pybind11 (#681)Use pybind11 for _rclpy_action (#678)Update just pycapsule lib to use pybind11 (#652)remove maintainer (#682)Use Pybind11’s CMake code (#667)Don’t call destroy_node while spinning (#674)Check the rcl_action return value on cleanup. (#672)Fix the NULL check for destroy_ros_message. (#677)Use Py_XDECREF for pynode_names_and_namespaces (#673)Use Py_XDECREF for pyresult_list. (#670)Fix dead stores. (#669)Fix two clang static analysis warnings. (#664)Add method to get the current logging directory (#657)Fix docstring indent error in create_node (#655)use only True to avoid confusion in autodoc configdocument QoS profile constantsMerge pull request#649from ros2/clalancette/dont-except-while-sleepFixes from review/CI.Make sure to catch the ROSInterruptException when calling rate.sleep.memory leak (#643) (#645)Don’t throw an exception if timer canceled while sleeping.Wake executor in Node.create_subscription() (#647)Fix Enum not being comparable with ints in get_parameter_types serviceQos configurability (#635)Use Py_XDECREF for pytopic_names_and_types. (#638)qos_policy_name_from_kind() should accept either a QoSPolicyKind or an int (#637)Add method in Node to resolve a topic or service name (#636)Deprecate verbose qos policy value names (#634)Remove deprecated set_parameters_callback (#633)Make sure to use Py_XDECREF in rclpy_get_service_names_and_types (#632)Update maintainers (#627)Add in semicolon on RCUTILS_LOGGING_AUTOINIT. (#624)Add in the topic name when QoS events are fired. (#621)Use best effort, keep last, history depth 1 QoS Profile for ‘/clock’ subscriptions (#619)PARAM_REL_TOL documentation fix (#559)Node get fully qualified name (#598)MultiThreadedExecutor spin_until_future complete should not continue waiting when the future is done (#605)skip test relying on source timestamps with Connext (#615)Use the rpyutils shared import_c_library function. (#610)Add ability to configure domain ID (#596)Use absolute parameter events topic name (#612)Destroy event handlers owned by publishers/subscriptions when calling publisher.destroy()/subscription.destroy() (#603)Default incompatible qos callback should be set when there’s no user specified callback (#601)relax rate jitter test for individual periods (#602)add QoSProfile.__str__ (#593)Add useful debug info when trying to publish the wrong type (#581)Pass rcutils_include_dirs to cppcheck (#577)wrap lines to shorten line length (#586)fix moved troubleshooting url (#579)improve error message if rclpy C extensions are not found (#580)Add message lost subscription event (#572)Fix executor behavior on shutdown (#574)Add missing rcutils/macros.h header (#573)Addtopic_nameproperty to Subscription (#571)Addtopic_nameproperty to publisher (#568)Fix and document rclpy_handle_get_pointer_from_capsule() (#569)Fix docstrings (#566)Contributors: Addisu Z. Taddese, Alejandro Hernández Cordero, Andrea Sorbini, Audrow, Audrow Nash, Barry Xu, Chris Lalancette, Claire Wang, Dereck Wonnacott, Dirk Thomas, Emerson Knapp, Greg Balke, Gökçe Aydos, Ivan Santiago Paunovic, Jacob Perron, Loy, Michel Hidalgo, Scott K Logan, Shane Loretz, Tomoya Fujita, Tully Foote, Zhen Ju, ksuszka, ssumoo, tomoyarcpputilsUpdate quality declaration links (#130)Add functions for getting library path and filename (#128)Add path equality operators (#127)Add create_temp_directory filesystem helper (#126)Use new noexcept specifier. (#123)Add stream operator for paths to make it easier to log (#120)Path join operator is const (#119)No windows.h in header files (#118)Fix rcpputils::SharedLibrary tests. (#117)Update QD to QL 1 (#114)Make sure to not try to index into an empty path. (#113)Fix working with filesystem parent paths. (#112)Cleanup mislabeled BSD license (#37)overload functions for has_symbol and get_symbol with raw string literal (#110)Add an ASSERT to the pointer traits tests. (#111)replace custom get env login into rcutils_get_env(). (#99)Removed Github Actions (#105)Update the package.xml files with the latest Open Robotics maintainers (#102)Make sure that an existing path is a directory for create_directories (#98)Transfer ownership to Open Robotics (#100)Ensure -fPIC is used when building a static lib (#93)Removed doxygen warnings (#86) (#87)Add clamp header (#85)Removed doxygen warnings (#86)Split get_env_var() into header and implementation (#83)Add cstring include for strcmp (#81)filesystem helpers: adding remove_all to remove non-empty directories (#79)Add scope_exit helper (#78)Bump setup-ros to 0.0.23, action-ros-lint to 0.0.6, action-ros-ci to 0.0.17 (#77)Fix parent_path() for empty paths and paths of length one (#73)Add get_executable_name() function (#70)Address memory leak in remove pointer test (#72)Add current_path to filesystem_helpers (#63)Align path combine behavior with C++17 (#68)Update quality declaration to QL 2 (#71)Contributors: Alejandro Hernández Cordero, Chen Lihui, Chris Lalancette, Christophe Bedard, Devin Bonnie, Dirk Thomas, Emerson Knapp, Hunter L. Allen, Ivan Santiago Paunovic, Jacob Perron, Karsten Knese, Louise Poubel, Michael Jeronimo, Michel Hidalgo, Nikolai Morin, Scott K Logan, Simon Honigmann, Stephen Brawner, Tully Foote, Victor Lopez, William Woodall, tomoyarcutilsDeclare dependency on libatomic (#338)updating quality declaration links (re:ros2/docs.ros2.org#52) (#335)Quiet down a warning in release mode. (#334)Make the logging separate char an implementation detail. (#332)Performance tests demo (#288)Remove references of __xstat (#330)Update the documentation to be more consistent. (#331)Shorten some excessively long lines of CMake (#328)qnx-support: include sys/link.h & avoid using dlinfo (#327)QNX uses XSI-compliant (#326)Add an API for directory iteration (#323)Fix a leak during error handling in dir size calculation (#324)Fix rcutils_shared_library_t path on Windows. (#322)Check linker flags instead of assuming compiler correlation. (#321)Improve shared library relative paths handling (#320)Update rcutils_calculate_directory_size() to support recursion (#306)Updating QD to QL 1 (#317)Address unused return values found in scan-build (#316)use one copy for continuous area instead of loop copy (#312)use a better way to check whether string is empty (#315)Use helper funciton to copy string (#314)Disable a Windows platform warning. (#311)Fix format of code description on document (#313)Make sure to check the return values of rcutils APIs. (#302)Add rcutils_expand_user() to expand user directory in path (#298)Update the maintainers. (#299)Remove the temporary variable in RCUTILS_LOGGING_AUTOINIT (#290)Add RCUTILS_NO_FAULT_INJECTION() macro. (#295)Inject faults on rcutils_get_env() and rcutils_set_env() call. (#292)env.h and get_env.h docblock fixes (#291)Introduce rcutils_strcasecmp, case insensitive string compare. (#280)Stop using fprintf to avoid using file handles by changing as few lines of code as possible. (#289)Defines QNX implementation for rcutils_get_platform_library_name (#287)Add RCUTILS_CAN_SET_ERROR_MSG_AND_RETURN_WITH_ERROR_OF() macro. (#284) To fault inject error messages as well as return codes.Change rcutils_fault_injection_set_count to use int64_t (#283)adds QNX support for rcutils_get_executable_name (#282)Add fault injection hooks to default allocator (#277)Fault injection macros and functionality (plus example) (#264)ensure -fPIC is used when building a static lib (#276)Drop vsnprintf mocks entirely. (#275) Binary API is not portable across platforms and compilation config.Fix vsnprintf mocks for Release builds. (#274)Improve test coverage mocking system calls (#272)Use mimick/mimick.h header (#273)Add mock test for rcutils/strerror (#265)Add compiler option -Wconversion and add explicit casts for conversions that may alter the value or change the sign (#263) Seehttps://github.com/ros2/rcutils/pull/263#issuecomment-663252537.Removed doxygen warnings (#266) (#268)Removed doxygen warnings (#266)Force _GNU_SOURCE if glibc is used. (#267)Add parenthesis around the argument in time conversion macros defined in time.h (#261)Add token join macros (#262)Add rcutils_string_array_sort function (#248)Add rcutils_string_array_resize function (#247)Increase testing coverage of rcutils to 95% (#258)Update QUALITY_DECLARATION to reflect QL 2 status (#260)Update version stability section of quality declaration for 1.0 (#256)Contributors: Ahmed Sobhy, Alejandro Hernández Cordero, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Dirk Thomas, Felix Endres, Homalozoa X, Ivan Santiago Paunovic, Johannes Meyer, Jorge Perez, Karsten Knese, Michel Hidalgo, Scott K Logan, Stephen Brawner, Steven! Ragnarök, brawner, shonigmann, tomoyaresource_retrieverThrow exception if package name is empty (#54)Update maintainers (#53)Add .hpp header and deprecate .h (#51)Add pytest.ini so local tests don’t display warning (#48)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jacob Perron, Shane LoretzrmwDocument which QoS policies are correctly read by rmw_get_publishers/subscriptions_info_by_topic (#308)Unique network flows (#294)updating quality declaration links (re:ros2/docs.ros2.org#52) (#307)Introduce RMW_DURATION_INFINITE constant and API return value promise (#301)Add declaration for function to check QoS profile compatibility (#299)Update the rmw_take_sequence documentation. (#297)Update rmw QD to QL 1 (#289)Extend rmw_qos_policy_kind_t, add functions to convert it to/from a string (#285)Add functions to convert between qos policy values and strings (#284)Update maintainers (#282)Update service request/response API documentation (#279)Update rmw_get_serialized_message_size docblock (#281)Update rmw_service_server_is_available doc (#280)Update wait and wait sets’ API documentation (#275)Update graph API documentation (#272)Update service server/client creation/destruction API documentation. (#276)Update rmw_*_*_allocation return values (#278)Update gid API documentation (#274)Do not link against pthread on Android (#267)Update taking API documentation (#271)Update publishing API documentation (#270)Add fault injection macros for use in other packages (#254)Add bad_alloc return to topic_endpoint_info functions (#269)Update publisher/subscription matched count API documentation (#262)Update publisher/subscription QoS query API documentation (#263)Extend rmw_serialized_message_t tests (#261)Update serialization/deserialization API documentation (#258)Update subscription API documentation (#256)Update publisher creation/destruction API documentation (#252)Add actual domain id to rmw_context_t (#251)Update node creation/destruction API documentation. (#249)Correct parameter names to match documentation (#250)Remove domain_id and localhost_only from node API (#248)Require enclave upon rmw_init() call. (#247)Update init/shutdown API documentation. (#243)Update init options API documentation. (#244)Add message lost subscription event (#232)Move statuses definitions to rmw/events_statuses/*.h (#232)Increase rmw testing coverage above 95% (#238)Handle zero-length names_and_types properly (#239)Add missing RMW_PUBLIC to security_options_set_root_path (#236)Update Quality Declaration for QL 2 (#233)Add Security Vulnerability Policy pointing to REP-2006. (#230)Contributors: Alejandro Hernández Cordero, Ananya Muddukrishna, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Ivan Santiago Paunovic, Jacob Perron, Karsten Knese, Michel Hidalgo, Scott K Logan, Stephen Brawner, brawner, shonigmannrmw_connextddsUse rmw_qos_profile_unknown when adding entity to graph (#28)Resolve issues identified while investigating#21(#22)Use Rolling in README’s Quick StartImproved implementation of client::is_service_available for Connext ProOnly add request header to typecode with Basic req/rep profileRemove commented/unused codeAvoid topic name validation in get_info functionsReduce shutdown period to 10msPass HistoryQosPolicy to graph cacheReset error string after looking up type supportRemove DDS-based WaitSet implementationMerge pull request#13from Ericsson/unique_network_flowsRefactor common APIUpdate branchmasterto support Rolling only (#15)Add ability to override of endpoint qos settings based on topic name.Optimize QoS for reliable large data.Only trigger data condition if samples were loaned from reader.Alternative WaitSet implementation based on C++ std, selectable at compile-time.Addforament_cmake.Use defaultdds.transport.UDPv4.builtin.ignore_loopback_interface.Renamed environment variables (RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE,RMW_CONNEXT_LEGACY_RMW_COMPATIBILITY_MODE).Support a list of initial peers viaRMW_CONNEXT_INITIAL_PEERS.Initial release.Contributors: Ananya Muddukrishna, Andrea Sorbini, Ivan Santiago Paunovic, William Woodallrmw_connextdds_commonCorrectly detect empty messages (#33)Use rmw_qos_profile_unknown when adding entity to graph (#28)Resolve issues identified while investigating#21(#22)Use Rolling in README’s Quick StartImproved implementation of client::is_service_available for Connext ProOnly add request header to typecode with Basic req/rep profileRemove commented/unused codeAvoid topic name validation in get_info functionsReduce shutdown period to 10msPass HistoryQosPolicy to graph cacheReset error string after looking up type supportRemove DDS-based WaitSet implementationMerge pull request#13from Ericsson/unique_network_flowsRemove superfluous header inclusionRemove conflicting linkageFurther remove feature-based exclusionRemove feature-based exclusionUncrustifyRefactor common APIInclude required headers if feature is enabledAdd conditional compilation supportPrefer more generic file nameRestrict unique flow endpoint check to versions beyond FoxyIndicate missing support for unique network flowsUpdate branchmasterto support Rolling only (#15)Add ability to override of endpoint qos settings based on topic name (Pro).Optimize QoS for reliable large data (Pro).Only trigger data condition if samples were loaned from reader.Alternative WaitSet implementation based on C++ std, selectable at compile-time.Addforament_cmake.Use defaultdds.transport.UDPv4.builtin.ignore_loopback_interface.Don’t log an error on WaitSet::wait() timeout.Initial release.Contributors: Ananya Muddukrishna, Andrea Sorbini, Ivan Santiago Paunovic, William Woodallrmw_connextddsmicroUse rmw_qos_profile_unknown when adding entity to graph (#28)Resolve issues identified while investigating#21(#22)Use Rolling in README’s Quick StartRemove commented/unused codeAvoid topic name validation in get_info functionsPass HistoryQosPolicy to graph cacheReset error string after looking up type supportRemove DDS-based WaitSet implementationMerge pull request#13from Ericsson/unique_network_flowsRefactor common APIUpdate branchmasterto support Rolling only (#15)Only trigger data condition if samples were loaned from reader.Alternative WaitSet implementation based on C++ std, selectable at compile-time.Addforament_cmake.Initial release.Contributors: Ananya Muddukrishna, Andrea Sorbini, Ivan Santiago Paunovic, William Woodallrmw_cyclonedds_cppFix the history depth for KEEP_ALL. (#305)Use the macros from Cyclone DDS to work with sample payload when using SHM (#300)Add loaned sample zero-copy API support (#297)Indicate missing support for unique network flows (#282)Take and return new RMW_DURATION_INFINITE correctly (#288)Add RMW function to check QoS compatibility (#286)Fix use-after-free in error handling bugDrop compatibility with ancient cyclone versionsUpdate to use Cyclone’s renamed ddsi_sertypeUse init-on-first-use for global state (#275)Make sure to reset the error when a typesupport can’t be found.Switch to using the generic functions for the typesupport handles.Handle typesupport errors on fetch. (#271)Handle potential divide by 0 (#267)Fix incorrect log message(rmw_fastrtps_shared_cpp -> rmw_cylonedds_cpp) (#260)Update maintainers (#254)Change wrong use of %ld to print std::size_t to %zuReturn RMW_RET_UNSUPPORTED in rmw_get_serialized_message_size (#250)Update service/client request/response API error returns (#249)Updated publisher/subscription allocation and wait set API return codes (#246)Fix arrayget_functionsemantics (#248)Update service/client construction/destruction API return codes. (#247)Update gid API return codes. (#244)Update graph API return codes. (#243)Check for message_info on take where appropriate. (#245) Fix for regression introduced in#241.Updated error returns on rmw_take_serialized() and rmw_take_with_message_info() (#242)Updated error returns on rmw_take() (#241)Add quality declaration for Cyclone DDS (#218)Fix that not to delete some objects after destroying functions (#236)Update rmw_publish_serialized_message() error returns (#240)Update rmw_publish() error returns (#239)Remove public declarations (#230)Use quotes for non-system includes (#231)Use correct functions to resize and get an item, avoiding memory leaks in typesupport code (#228)Fix context cleanup. (#227)Fix memory leak that type support not deleted. (#225)Ensure compliant matched pub/sub count API. (#223)Fix memory leak that string not deleted. (#224)Change RET_WRONG_IMPLID() to return RMW_RET_INCORRECT_IMPLEMENTATION (#226)Fix bad conditional in rmw_serialize(). (#217)Ensure compliant subscription API. (#214)Ensure compliant publisher API (#210)rmw_destroy_node must remove node from graph cache (#213)Add space between ‘ROS’ and ‘2’ (#195)Set context actual domain id (#208)Ensure compliant node construction/destruction API (#206)Remove domain_id and localhost_only from node API (#205)Amend rmw_init() implementation: require enclave. (#204)Ensure compliant init/shutdown API implementations. (#202)Ensure compliant init options API implementations. (#200)Finalize context iff shutdown. (#196)Handle RMW_DEFAULT_DOMAIN_ID. (#194)Add support to message lost event (#192)Mitigate lost service responses discovery issue (#187)Contributors: Alejandro Hernández Cordero, Ananya Muddukrishna, Chen Lihui, Chris Lalancette, Christophe Bedard, Dan Rose, Emerson Knapp, Erik Boasson, Ivan Santiago Paunovic, Jacob Perron, Joe Speed, Jose Tomas Lorente, Lobotuerk, Michel Hidalgo, Scott K Logan, Stephen Brawner, Sumanth Nirmal, Sven Brinkmann, eboasson, plurisrmw_dds_commonFix one more instance of index.ros.org. (#49)updating quality declaration links (re:ros2/docs.ros2.org#52) (#46)Add function for checking QoS profile compatibility (#45)Shorten some excessively long lines of CMake (#44)Fix test_graph_cache ASAN errors (#41) (#42)Update QD to QL 1 (#38)Create a utility function to limit rmw_time_t to 32-bit values (#37)Update maintainers (#34)Updated performance section QD (#30)Update Quality Declaration to QL2 (#31)Added benchmark test to rmw_dds_common (#29)Fix potential memory leak (#28)Add fault injection macro unit tests (#27)Fixed some doxygen warnings (#26)Update Quality Declaration to QL3 (#24)Update QD and documentation (#23)Contributors: Alejandro Hernández Cordero, Chen Lihui, Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Michael Jeronimo, Michel Hidalgo, Scott K Logan, Stephen Brawner, shonigmann, y-okumura-isprmw_fastrtps_cppRefactor to use DDS standard API (#518)Unique network flows (#502)updating quality declaration links (re:ros2/docs.ros2.org#52) (#520)Add RMW function to check QoS compatibility (#511)Capture cdr exceptions (#505)Load profiles based on topic names (#335)Set rmw_dds_common::GraphCache callback after init succeeds. (#496)Handle typesupport errors on fetch. (#495)Check for correct context shutdown (#486)New environment variable to change easily the publication mode (#470)Discriminate when the Client has gone from when the Client has not completely matched (#467) * Workaround when the client is gone before server sends response * Change add to the map to listener callbackUpdate the package.xml files with the latest Open Robotics maintainers (#459)Update Quality Declarations and READMEs (#455) * Add QD links for dependencies to rmw_fastrtps_cpp QD * Provide external dependencies QD links * Update rmw_fastrtps README to use Fast DDS * Update rmw_fastrtps_cpp QD: Fast DDS & unit test * Update README rmw_fastrtps_cpp to QL2Perform fault injection in all creation/destruction APIs. (#453)Ensure rmw_destroy_node() completes despite run-time errors. (#458)Update rmw_fastrtps_cpp and rmw_fastrtps_shared_cpp QDs to QL2. (#456)Return RMW_RET_UNSUPPORTED in rmw_get_serialized_message_size (#452)Updated publisher/subscription allocation and wait set API return codes (#443)Added rmw_logging tests (#442)Make service/client construction/destruction implementation compliant (#445)Make sure type can be unregistered successfully (#437)Add tests for native entity getters. (#439)Avoid deadlock if graph update fails. (#438)Call Domain::removePublisher while failure occurs in create_publisher (#434)Ensure compliant matched pub/sub count API. (#424)Ensure compliant publisher QoS queries. (#425)Ensure compliant subscription API. (#419)Ensure compliant publisher API. (#414)Set context actual domain id (#410)Ensure compliant node construction/destruction API. (#408)Remove domain_id and localhost_only from node API (#407)Amend rmw_init() implementation: require enclave. (#406)Update Quality Declarations to QL3. (#404)Ensure compliant init/shutdown API implementation. (#401)Update Quality Declaration to QL3. (#403)Finalize context iff shutdown. (#396)Make service wait for response reader (#390)Contributors: Alejandro Hernández Cordero, Barry Xu, Eduardo Ponz Segrelles, Ignacio Montesino Valle, Ivan Santiago Paunovic, JLBuenoLopez-eProsima, Jacob Perron, Jaime Martin Losa, José Luis Bueno López, Michael Jeronimo, Michel Hidalgo, Miguel Company, shonigmannrmw_fastrtps_dynamic_cppRefactor to use DDS standard API (#518)Unique network flows (#502)updating quality declaration links (re:ros2/docs.ros2.org#52) (#520)Add RMW function to check QoS compatibility (#511)Capture cdr exceptions (#505)Load profiles based on topic names in rmw_fastrtps_dynamic_cpp (#497)Set rmw_dds_common::GraphCache callback after init succeeds. (#496)Handle typesupport errors on fetch. (#495)Check for correct context shutdown (#486)New environment variable to change easily the publication mode (#470)Discriminate when the Client has gone from when the Client has not completely matched (#467) * Workaround when the client is gone before server sends response * Change add to the map to listener callbackUpdate the package.xml files with the latest Open Robotics maintainers (#459)Update Quality Declarations and READMEs (#455) * Add QL of external dependencies to rmw_fastrtps_dynamic_cpp QD * Add QD links for dependencies to rmw_fastrtps_dynamic_cpp QD * Provide external dependencies QD links * Add README to rmw_fastrtps_dynamic * Add QD for rmw_fastrtps_dynamicEnsure rmw_destroy_node() completes despite run-time errors. (#458)Return RMW_RET_UNSUPPORTED in rmw_get_serialized_message_size (#452)Updated publisher/subscription allocation and wait set API return codes (#443)Added rmw_logging tests (#442)Fix arrayget_functionsemantics (#448)Make service/client construction/destruction implementation compliant (#445)Make sure type can be unregistered successfully (#437)Add tests for native entity getters. (#439)Avoid deadlock if graph update fails. (#438)Call Domain::removePublisher while failure occurs in create_publisher (#434)Avoid memory leaks and undefined behavior in rmw_fastrtps_dynamic_cpp typesupport code (#429)Ensure compliant matched pub/sub count API. (#424)Ensure compliant publisher QoS queries. (#425)Ensure compliant subscription API. (#419)Ensure compliant publisher API. (#414)Set context actual domain id (#410)Ensure compliant node construction/destruction API. (#408)Remove domain_id and localhost_only from node API (#407)Amend rmw_init() implementation: require enclave. (#406)Ensure compliant init/shutdown API implementation. (#401)Finalize context iff shutdown. (#396)Make service wait for response reader (#390)Contributors: Alejandro Hernández Cordero, Barry Xu, Eduardo Ponz Segrelles, Ignacio Montesino Valle, Ivan Santiago Paunovic, JLBuenoLopez-eProsima, Jacob Perron, Jaime Martin Losa, José Luis Bueno López, Michael Jeronimo, Michel Hidalgo, Miguel Company, shonigmannrmw_fastrtps_shared_cppRefactor to use DDS standard API (#518)Unique network flows (#502)updating quality declaration links (re:ros2/docs.ros2.org#52) (#520)Take and return new RMW_DURATION_INFINITE correctly (#515)Add RMW function to check QoS compatibility (#511)Capture cdr exceptions (#505)Make sure to lock the mutex protecting client_endpoints_. (#492)Use interface whitelist for localhost only (#476)Make use of error return value in decrement_context_impl_ref_count (#488)Remove unnecessary includes (#487)Use new time_utils function to limit rmw_time_t values to 32-bits (#485)New environment variable to change easily the publication mode (#470)Remove unused headers MessageTypeSupport.hpp and ServiceTypeSupport.hpp (#481)Discriminate when the Client has gone from when the Client has not completely matched (#467) * Workaround when the client is gone before server sends response * Change add to the map to listener callbackUpdate the package.xml files with the latest Open Robotics maintainers (#459)Update Quality Declarations and READMEs (#455) * Add QD links for dependencies to rmw_fastrtps_shared_cpp QD. * Provide external dependencies QD links. * Update rmw_fastrtps_shared_cpp QD: Fast DDS * Update README rmw_fastrtps_shared_cpp to QL2Perform fault injection in all creation/destruction APIs. (#453)Ensure rmw_destroy_node() completes despite run-time errors. (#458)Handle too large QoS queue depths. (#457)Update rmw_fastrtps_cpp and rmw_fastrtps_shared_cpp QDs to QL2. (#456)checked client implementation and return RMW_RET_INCORRECT_RMW_IMPLEMENTATION (#451)Update service/client request/response API error returns (#450)Updated publisher/subscription allocation and wait set API return codes (#443)Added rmw_logging tests (#442)Add tests for RMW QoS to DDS attribute conversion. (#449)Make service/client construction/destruction implementation compliant (#445)Inject faults on __rmw_publish() and run_listener_thread() call. (#441)Update gid API return codes. (#440)Update graph API return codes. (#436)Update rmw_take_serialized() and rmw_take_with_message_info() error returns (#435)Update rmw_take() error returns (#432)Update rmw_publish() error returns (#430)Update rmw_publish_serialized_message() error returns (#431)Improve __rmw_create_wait_set() implementation. (#427)Ensure compliant matched pub/sub count API. (#424)Ensure compliant publisher QoS queries. (#425)Fix memory leak that wait_set might be not destoryed in some case. (#423)Avoid unused identifier variable warnings. (#422)Fix trying to get topic data that was already removed. (#417)Ensure compliant subscription API. (#419)Use package path to TypeSupport.hpp headers in ServiceTypeSupport and MessageTypeSupport (#415) Use package in path to TypeSupport header for ServiceTypeSupport/MessageTypeSupportEnsure compliant publisher API. (#414)Set context actual domain id (#410)Add missing thread-safety annotation in ServicePubListener (#409)Ensure compliant node construction/destruction API. (#408)Update Quality Declarations to QL3. (#404)Do not use string literals as implementation identifiers in tests. (#402)Ensure compliant init options API implementations. (#399)Finalize context iff shutdown. (#396)Handle RMW_DEFAULT_DOMAIN_ID. (#394)Make service wait for response reader (#390)Contributors: Alejandro Hernández Cordero, Chen Lihui, Chris Lalancette, Emerson Knapp, Ivan Santiago Paunovic, JLBuenoLopez-eProsima, Jacob Perron, Jaime Martin Losa, Jose Luis Rivero, Jose Tomas Lorente, José Luis Bueno López, Lobotuerk, Michael Jeronimo, Michel Hidalgo, Miguel Company, Stephen Brawner, shonigmannrmw_implementationUnique network flows (#170)updating quality declaration links (re:ros2/docs.ros2.org#52) (#185)Remove rmw_connext_cpp. (#183)Add support for rmw_connextdds (#182)Add function for checking QoS profile compatibility (#180)Shorten some excessively long lines of CMake (#179)Add rmw_fastrtps_dynamic_cpp to the explicit group deps (#177)Accept any RMW implementation, not just the default (#172)Defer path resolution of rmw implementation libraries to dynamic linker. (#169)Update QD to QL 1 (#166)Fix up C functions to never throw. (#149)Restored Dirk as author (#155)Update maintainers (#154)Updated performance QD section (#153)Update Quality Declaration to QL2. (#151)Add nominal test for symbol prefetch() and unload. (#145)Added benchmark test to rmw_implementation (#127)Test load and lookup functionality. (#135)Remove domain_id and localhost_only from node API (#114)Move the quality declaration into the rmw_implementation subdirectory. (#111)Contributors: Alejandro Hernández Cordero, Ananya Muddukrishna, Andrea Sorbini, Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgo, Scott K Logan, Stephen Brawner, shonigmannrmw_implementation_cmakeShorten some excessively long lines of CMake (#300)Change default RMW vendor to CycloneDDS. (#293)Update rmw QD to QL 1 (#289)Update maintainers (#282)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Scott K Logan, Stephen Brawnerrobot_state_publisherStop rejecting unknown parameters. (#161)clean up license to be standard bsd 3 clause (#130)Update the maintainers. (#151)fix types in range loops to avoid copy due to different type (#143)Make sure not to crash on an invalid URDF. (#141)Don’t export exe as library (#25) (ros2 #28)Contributors: Chris Lalancette, Dirk Thomas, Tully Footeros1_bridgeFix logging for updated rclcpp interface (#303)Fix typo in comments (#297)Update to use rosidl_parser and .idl files rather than rosidl_adapter and .msg files (#296)Update maintainers (#286)use hardcoded QoS (keep all, transient local) for /tf_static topic in dynamic_bridge (#282)document explicitly passing the topic type to ‘ros2 topic echo’ (#279)Fix multiple definition if message with same name as service exists (#272)Contributors: Dirk Thomas, Jacob Perron, Michael Carroll, Vicidel, William Woodallros2actionAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovicros2bag/clock publisher in Player (#695)Introducing Reindexer CLI (#699)rosbag2_py pybind wrapper for “record” - remove rosbag2_transport_py (#702)Add rosbag2_py::Player::play to replace rosbag2_transport_python version (#693)Explicitly add emersonknapp as maintainer (#692)use rosbag2_py for ros2 bag info (#673)CLI query rosbag2_py for available storage implementations (#659)Recorder –regex and –exclude options (#604)Fix the tests on cyclonedds by translating qos duration values (#606)SQLite storage optimized by default (#568)Fix a bug on parsing wrong description in plugin xml file (#578)Compress bag files in separate threads (#506)Sqlite storage double buffering (#546) * Double buffers * Circular queue and FLUSH option as define * Minor naming and lexical fixes. * Removed FLUSH_BUFFERS define check. * Sqlite3 storage logging fixes. * Sqlite3 storage circular buffer with pre allocated memory. * Sqlite3 storage buffers moved to shared_ptrs. * Uncrustify * Moved double buffers to writer * Buffer layer reset in seq compression writer in rosbag2 cpp * Buffer layer for rosbag2 writer refactor * Changed buffers in BufferLayer to std vectors. * BufferLayer uncrustify * Removed non-applicable test for writer cache. * BufferLayer review fixes * Rosbag metadata msgs count fixed for BufferLayer * Condition variable for buffer layer sync. * Fixed buffer locks * Buffers in BufferLayer refactored, moved into new class * Buffer layer split bags fixed. * Storage options include fix in buffer layer header. * Mutex around swapping buffers in buffer layer. * Fixed cache 0 bug in buffer layer. * Minor buffer layer refactor. * Counting messages in writer refactored. * Changed default cache size to 100Mb and updated parameter description * Applied review remarks: - significant refactoring: separation of cache classes - applied suggested improvements - some renaming - reduce code duplication that would otherwise increase with cache refactor, between compression and plain writers * Applied review comments - cache consumer now takes a callback and is independent of storage - namespace changes, renaming, cleaning - counting and logging messages by topic * linter * Changes after review: fixing flushing, topic counts, and more * Fix for splitting - flushing state now correctly turns off * cache classes documentation * simplified signature * a couple of tests for cache * address review: explicit constructor and doxygen styling * Windows warnings fix * fixed type mismatch warning on Windows * added minor comment Co-authored-by: Piotr Jaroszek read yaml config file (#497)List all storage plugins in plugin xml file (#554)add storage_config_uri (#493)Update deprecated qos policy value names (#548)Add record test for ros2bag (#523)Removed duplicated code in record (#534)Change default cache size for sequential_writer to a non zero value (#533)Update the package.xml files with the latest Open Robotics maintainers (#535)[ros2bag test_record] Gets rid of time.sleep and move to using command.wait_for_output (#525)Add pytest.ini back to ros2bag. (#492)performance testing packages (#442)Validate QoS profile values are not negative. (#483)catch parent exception (#472)add wait for closed file handles on Windows (#470)introduce ros2 bag list (#468)move wait_for_shutdown() call out of the context manager (#466)Adding db directory creation to rosbag2_cpp (#450)use a single temp dir for the test class (#462)Add per-message ZSTD compression (#418)Add split by time to recording (#409)Add pytest.ini so local tests don’t display warning (#446)Contributors: Adam Dąbrowski, Barry Xu, Chris Lalancette, Dirk Thomas, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jaison Titus, Jesse Ikawa, Karsten Knese, Marwan Taher, Michael Jeronimo, P. J. Reed, jhdcsros2cliAdd changelog. (#636)Ensure only one daemon can run at a time. (#622)Remove maintainer. (#597)Add option to support use_sim_time. (#581)Bugfix for#563. (#570)Add Audrow as a maintainer. (#591)Support Python 3.8-provided importlib.metadata. (#585)Update maintainers. (#568)Added dependency to python3-argcomplete to ros2cli. (#564)Remove use of pkg_resources from ros2cli. (#537)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Daisuke Sato, Ivan Santiago Paunovic, Michel Hidalgo, Scott K Logan, Tomoya Fujita, Yoan Mollardros2cli_common_extensionsremove maintainer (#5)update maintainer (#4)First implementation (#2)Contributors: Bo Sun, Claire Wangros2cli_test_interfacesAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Make ros2cli_test_interfaces version equal to other packages.Remove ros2interface test dependencies on builtin interface. (#579)Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Ivan Santiago Paunovicros2componentAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Ensure consistent timeout in ros2component list. (#526)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovic, Michel Hidalgoros2doctorImprove ros2 doctor on Windows. (#631) (#634)Add changelog. (#636)Continue to next iteration after exceptions in generate_reports. (#623)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Support Python 3.8-provided importlib.metadata. (#585)Update maintainers. (#568)Remove pkg_resources from ros2doctor. (#537)Make ros2doctor depend on ros_environment and fix platform.py bug on error. (#538)Refactor ros2doctor hello verb. (#521)Contributors: Alberto Soragna, Audrow Nash, Chris Lalancette, Claire Wang, Ivan Santiago Paunovic, Michel Hidalgo, Scott K Logan, mergify[bot]ros2interfaceAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Remove ros2interface test dependencies on builtin interface. (#579)Update maintainers. (#568)Handle inline comments on constants correctly. (#548)Update quoted comments in the test (#540)Add option to include/remove whitespace and comments. (#527)Show “expanded” message definition. (#524)Contributors: Audrow, Audrow Nash, Claire Wang, Ivan Santiago Paunovic, Tully Footeros2launchAdd options extensions to ros2launch and extensibility to the node action (#216)Support non-interactive ros2 launch executions (#210)Merge pull request#183from ros2/update-maintainersMove previous maintainer to Update the package.xml files with the latest Open Robotics maintainersAdd pytest.ini so local tests don’t display warning (#152)Contributors: Chris Lalancette, Geoffrey Biggs, Michael Jeronimo, Michel Hidalgoros2lifecycleAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovicros2lifecycle_test_fixturesAdd changelog. (#636)Depend on rclcpp::rclcpp target. (#618) Contributors: Audrow NashRemove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovicros2multicastAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovicros2nodeAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovicros2paramAdd changelog. (#636)Make the ros2param –filter test more reliable. (#606)Add wildcard loading to ros2 param load. (#602)Ros2 param dump/load should use fully qualified node names. (#600)Add –filter options for ‘ros2 param list’. (#592)Remove maintainer. (#597)Add rosparam verb load. (#590)Add Audrow as a maintainer. (#591)Add “–param-type” option to ros2param list. (#572)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovic, Victor Lopez, tomoyaros2pkgAdd changelog. (#636)Use underscores in setup.cfg.em instead of dashes. (#627)Add space for “ROS 2”. (#617)Use target_compile_features for c/c++ standards. (#615)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Declare missing dependency on python3-importlib-resources. (#584)Update maintainers. (#568)Fix incorrect EXPORT for executables. (#545)Switch ros2pkg to using importlib.Contributors: Audrow Nash, Chris Lalancette, Claire Wang, Dirk Thomas, Ivan Santiago Paunovic, Scott K Logan, Shane Loretzros2runAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Contributors: Audrow Nash, Claire Wang, Ivan Santiago Paunovicros2serviceAdd changelog. (#636)Remove maintainer. (#597)Add Audrow as a maintainer. (#591)Update maintainers. (#568)Check that passed type is actually a service. (#559)Contributors: Audrow Nash, Claire Wang, Dirk Thomas, Ivan Santiago Paunovicros2testAdd pytest.ini so local tests don’t display warning (#8)Contributors: Chris Lalancetteros2topicAdd changelog. (#636)Add verbose info for topic list. (#351)Remove maintainer. (#597)Add option to support use_sim_time. (#581)Add Audrow as a maintainer. (#591)Add filter option to ros2topic . (#575)Update deprecated qos policy value names. (#571)Update maintainers. (#568)Fix the test to use the topic name. (#566)Improve the error message for invalid message types. (#558)Use reliable QoS for ros2topic tests. (#555)Add option to echo serialized messages. (#470)Enable –no-daemon flag for some cli tools. (#514)Use transient_local and longer keep-alive for pub tests. (#546)Add –keep-alive option to ‘topic pub’. (#544)Add option to ros2 topic echo to report lost messages. (#542)Support QoS Depth and History via ros2 topic pub/echo. (#528)Contributors: Audrow Nash, ChenYing Kuo, Chris Lalancette, Claire Wang, Dereck Wonnacott, Dirk Thomas, Ivan Santiago Paunovic, Jacob Perron, Scott K Logan, Tomoya Fujita, tomoyaros_testingUse rostest CMake target as output file basename. (#9)Contributors: Michel Hidalgorosbag2Explicitly add emersonknapp as maintainer (#692)RMW-implementation-searcher converter in rosbag2_cpp (#670)Move zstd compressor to its own package (#636)add storage_config_uri (#493)Update the package.xml files with the latest Open Robotics maintainers (#535)AMENT_IGNORE rosbag2_py for now (#509)rosbag2_py reader and writer (#308)Contributors: Emerson Knapp, Karsten Knese, Mabel Zhang, Michael Jeronimorosbag2_compressionExplicitly add emersonknapp as maintainer (#692)Reindexer core (#641) Add a new C++ Reindexer class for reconstructing metadata from bags that are missing it.CLI query rosbag2_py for available storage implementations (#659)Move zstd compressor to its own package (#636)Remove rosbag2_compression test dependencies on zstd implementation in prep for moving it into a separate package (#637)Make compressor implementations into a plugin via pluginlib (#624)Use ZSTD’s streaming interface for [de]compressing files (#543)Fix build issues when rosbag2_storage is binary installed (#585)Fix relative metadata paths in SequentialCompressionWriter (#613)Fix deadlock race condition on compression shutdown (#616)Deduplicate SequentialCompressionReader business logic, add fallback to find bagfiles in incorrectly-written metadata (#612)Compress bag files in separate threads (#506)Sqlite storage double buffering (#546)add storage_config_uri (#493)Update the package.xml files with the latest Open Robotics maintainers (#535)Do not expect empty StorageOptions URI to work in CompressionWriterTest (#526)Remove some code duplication between SequentialWriter and SequentialCompressionWriter (#527)Fix exception thrown given invalid arguments with compression enabled (#488)Adding db directory creation to rosbag2_cpp (#450)Consolidate ZSTD utility functions (#459)Add per-message ZSTD compression (#418)Contributors: Adam Dąbrowski, Christophe Bedard, Devin Bonnie, Emerson Knapp, Jaison Titus, Karsten Knese, Marwan Taher, Michael Jeronimo, P. J. Reed, jhdcsrosbag2_compression_zstdAdd test_depend ament_cmake_gmock (#639)Move zstd compressor to its own package (#636)Contributors: Emerson Knapp, Shane Loretzrosbag2_cppAdd set_rate to PlayerClock (#727)Enforce non-null now_fn in TimeControllerClock (#731)Fix pause snapshot behavior and add regression test (#730)Pause/resume PlayerClock (#704)Remove -Werror from builds, enable it in Action CI (#722)Enable thread safety analysis for rosbag2_cpp and add annotations in TimeControllerClock (#710)PlayerClock initial implementation - Player functionally unchanged (#689)Explicitly add emersonknapp as maintainer (#692)Reindexer core (#641) Add a new C++ Reindexer class for reconstructing metadata from bags that are missing it.use rclcpp serialized messages to write data (#457)alternative write api (#676)RMW-implementation-searcher converter in rosbag2_cpp (#670)CLI query rosbag2_py for available storage implementations (#659)Fix –topics flag for ros2 bag play being ignored for all bags after the first one. (#619)Fix a crash in test_message_cache. (#635)Fix build issues when rosbag2_storage is binary installed (#585)Deduplicate SequentialCompressionReader business logic, add fallback to find bagfiles in incorrectly-written metadata (#612)include what you use (#600)Only dereference the data pointer if it is valid. (#581)Add back rosbag2_cpp::StorageOptions as deprecated (#563)Sqlite storage double buffering (#546)correct master build (#552)add storage_config_uri (#493)Mutex around writer access in recorder (#491)if cache data exists, it needs to flush the data into the storage before shutdown (#541)Change default cache size for sequential_writer to a non zero value (#533)SequentialWriter to cache by message size instead of message count (#530)Update the package.xml files with the latest Open Robotics maintainers (#535)Remove some code duplication between SequentialWriter and SequentialCompressionWriter (#527)disable sanitizer by default (#517)Fix typo in error message (#475)introduce defaults for the C++ API (#452)Adding db directory creation to rosbag2_cpp (#450)comment out unused variable (#460)minimal c++ API test (#451)Add split by time to recording (#409)Contributors: Adam Dąbrowski, Alexander, Chris Lalancette, Dirk Thomas, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jaison Titus, Karsten Knese, Marwan Taher, Michael Jeronimo, P. J. Reed, Patrick Spieler, Tomoya Fujita, jhdcsrosbag2_interfacesAdd rosbag2_interfaces package with playback service definitions (#728)Contributors: Emerson Knapprosbag2_performance_benchmarkingfixed a memory leak in no-transport benchmark (#674)report of performance improvements in rosbag2 (roughly since Foxy) (#651)Performance benchmarking improvements (#634)Performance benchmarking refactor (#594)Sqlite storage double buffering (#546)read yaml config file (#497)add storage_config_uri (#493)Update the package.xml files with the latest Open Robotics maintainers (#535)performance testing packages (#442)Contributors: Adam Dąbrowski, Karsten Knese, Michael Jeronimo, Piotr Jaroszekrosbag2_pyRemove -Werror from builds, enable it in Action CI (#722)Split Rosbag2Transport into Player and Recorder classes - first pass to enable further progress (#721)/clock publisher in Player (#695)Introducing Reindexer CLI (#699)Fix rosbag2_py transport test for py capsule (#707)rosbag2_py pybind wrapper for “record” - remove rosbag2_transport_py (#702)Add rosbag2_py::Player::play to replace rosbag2_transport_python version (#693)Explicitly add emersonknapp as maintainer (#692)RMW-implementation-searcher converter in rosbag2_cpp (#670)use rosbag2_py for ros2 bag info (#673)CLI query rosbag2_py for available storage implementations (#659)Fix build issues when rosbag2_storage is binary installed (#585)Fix the tests on cyclonedds by translating qos duration values (#606)add storage_config_uri (#493)Workaround pybind11 bug on Windows when CMAKE_BUILD_TYPE=RelWithDebInfo (#538)Update the package.xml files with the latest Open Robotics maintainers (#535)Fix rosbag2_py on Windows debug and stop ignoring the package (#531)Fix rosbag2_py bug when using libc++ (#529)AMENT_IGNORE rosbag2_py for now (#509)rosbag2_py reader and writer (#308)Contributors: Emerson Knapp, Ivan Santiago Paunovic, Karsten Knese, Mabel Zhang, Michael Jeronimo, P. J. Reed, jhdcsrosbag2_storageRemove -Werror from builds, enable it in Action CI (#722)PlayerClock initial implementation - Player functionally unchanged (#689)Explicitly add emersonknapp as maintainer (#692)Reindexer core (#641) Add a new C++ Reindexer class for reconstructing metadata from bags that are missing it.Remove outdated pluginlib cmake script from rosbag2_storage (#661)CLI query rosbag2_py for available storage implementations (#659)Shorten some excessively long lines of CMake (#648)SQLite storage optimized by default (#568) * Use optimized pragmas by default in sqlite storage. Added option to use former behaviorUse std::filesystem compliant non-memberexistsfunction for path object (#593)Update codes since rcutils_calculate_directory_size() is changed (#567)add storage_config_uri (#493)Update the package.xml files with the latest Open Robotics maintainers (#535)Add split by time to recording (#409)Contributors: Adam Dąbrowski, Barry Xu, Emerson Knapp, Josh Langsfeld, Karsten Knese, Michael Jeronimo, Scott K Logan, jhdcsrosbag2_storage_default_pluginsRemove -Werror from builds, enable it in Action CI (#722)Explicitly add emersonknapp as maintainer (#692)Reindexer core (#641) Add a new C++ Reindexer class for reconstructing metadata from bags that are missing it.Fix build issues when rosbag2_storage is binary installed (#585)Mutex protection for db writing and stl collections in writer & storage (#603)SQLite storage optimized by default (#568)read yaml config file (#497)add storage_config_uri (#493)Update the package.xml files with the latest Open Robotics maintainers (#535)Contributors: Adam Dąbrowski, Emerson Knapp, Karsten Knese, Michael Jeronimo, P. J. Reed, jhdcsrosbag2_test_commonRemove -Werror from builds, enable it in Action CI (#722)Fix bad_function_call by replacing rclcpp::spin_some with SingleThreadedExecutor (#705)Explicitly add emersonknapp as maintainer (#692)Remove temporary directory platform-specific logic from test fixture (#660)Stabilize test_record by reducing copies of executors and messages (#576)Update the package.xml files with the latest Open Robotics maintainers (#535)Contributors: Emerson Knapp, Michael Jeronimorosbag2_testsRemove -Werror from builds, enable it in Action CI (#722)Explicitly add emersonknapp as maintainer (#692)Reindexer core (#641) Add a new C++ Reindexer class for reconstructing metadata from bags that are missing it.use rclcpp serialized messages to write data (#457)Alternative write api (#676)RMW-implementation-searcher converter in rosbag2_cpp (#670)Use rosbag2_py for ros2 bag info (#673)Remove temporary directory platform-specific logic from test fixture (#660)Fix –topics flag for ros2 bag play being ignored for all bags after the first one. (#619)Move zstd compressor to its own package (#636)Fix relative metadata paths in SequentialCompressionWriter (#613)Recorder –regex and –exclude options (#604)Fix the tests on cyclonedds by translating qos duration values (#606)add storage_config_uri (#493)Removed duplicated code in record (#534)Change default cache size for sequential_writer to a non zero value (#533)Update the package.xml files with the latest Open Robotics maintainers (#535)Mark flaky tests as xfail for now (#520)introduce defaults for the C++ API (#452)Adding db directory creation to rosbag2_cpp (#450)minimal c++ API test (#451)Add split by time to recording (#409)Contributors: Adam Dąbrowski, Alexander, Emerson Knapp, Jaison Titus, Karsten Knese, Marwan Taher, Michael Jeronimo, jhdcsrosbag2_transportcleanup cmakelists (#726)turn recorder into a node (#724)turn player into a node (#723)Remove -Werror from builds, enable it in Action CI (#722)Split Rosbag2Transport into Player and Recorder classes - first pass to enable further progress (#721)/clock publisher in Player (#695)use rclcpp logging macros (#715)use rclcpp::Node for generic pub/sub (#714)PlayerClock initial implementation - Player functionally unchanged (#689)Fix bad_function_call by replacing rclcpp::spin_some with SingleThreadedExecutor (#705)rosbag2_py pybind wrapper for “record” - remove rosbag2_transport_py (#702)Add rosbag2_py::Player::play to replace rosbag2_transport_python version (#693)Fix and clarify logic in test_play filter test (#690)Explicitly add emersonknapp as maintainer (#692)Add QoS decoding translation for infinite durations to RMW_DURATION_INFINITE (#684)Add support for rmw_connextdds (#671)Use rosbag2_py for ros2 bag info (#673)Fix build issues when rosbag2_storage is binary installed (#585)Regex and exclude fix for rosbag recorder (#620)Recorder –regex and –exclude options (#604)SQLite storage optimized by default (#568)Fixed playing if unknown message types exist (#592)Compress bag files in separate threads (#506)Stabilize test_record by reducing copies of executors and messages (#576)add storage_config_uri (#493)Update the package.xml files with the latest Open Robotics maintainers (#535)resolve memory leak for serialized message (#502)Use shared logic for importing the rosbag2_transport_py library in Python (#482)fix missing target dependencies (#479)reenable cppcheck for rosbag2_transport (#461)More reliable topic remapping test (#456)Add split by time to recording (#409)export shared_queues_vendor (#434)Contributors: Adam Dąbrowski, Andrea Sorbini, Chen Lihui, Dirk Thomas, Emerson Knapp, Karsten Knese, Michael Jeronimo, P. J. Reed, Piotr Jaroszek, jhdcsrosgraph_msgsChange index.ros.org -> docs.ros.org. (#122)Updating Quality Declaration (#120)Update README.md (#119)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannrosidl_adapterExpose .msg/.srv/.action to .idl conversion via rosidl translate CLI (#576)Support hex constants in msg files (#559)Treat t as whitespace (#557)Update the maintainers of this repository. (#536)Refactor regex for valid package/field names (#508)Add pytest.ini so tests succeed locally (#502)Contributors: Chris Lalancette, Dereck Wonnacott, Dirk Thomas, Michel Hidalgorosidl_cliAlign rosidl_cli package version with the rest of the repo. (#579)Expose an API for each rosidl CLI command. (#577)Add rosidl translate CLI. (#575)Add rosidl generate CLI. (#567)Contributors: Michel Hidalgo, Shane Loretzrosidl_cmakeShorten some excessively long lines of CMake (#571)Update the maintainers of this repository. (#536)Modifications to python generator lib to return generated files (#511)Contributors: Alex Tyshka, Chris Lalancette, Scott K Loganrosidl_default_generatorsUpdate maintainers (#13)Contributors: Shane Loretzrosidl_default_runtimeupdating quality declaration links (re:ros2/docs.ros2.org#52) (#18)Update QD to QL 1 (#15)Update maintainers (#13)Updated QD to 2 in README.md (#12)Update rosidl_default_runtime QD to QL2. (#11)Bump the QUALITY_DECLARATION to level 3. (#10)Add Security Vulnerability Policy pointing to REP-2006. (#9)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Shane Loretz, Stephen Brawner, shonigmannrosidl_generator_cExpose C code generation via rosidl generate CLI (#569)Strip action service suffixes from C include prefix (#538)Update the maintainers of this repository. (#536)Fix the declared language for a few packages (#530)Do not depend on rosidl_runtime_c when tests are disabled (#503)Contributors: Ben Wolsieffer, Chris Lalancette, Jacob Perron, Michel Hidalgo, Scott K Loganrosidl_generator_cppExpose C++ code generation via rosidl generate CLI (#570)Switch to std::allocator_traits. (#564)Remove unnecessary assert on pointer created with new (#555)Use ASSERT_TRUE to check for nullptr. (#543)Update the maintainers of this repository. (#536)Add to_yaml() function for C++ messages (#527)Add function for getting a types fully qualified name (#514)Declaring is_message in namespace rosidl_generator_traits (#512)Contributors: Chris Lalancette, Devin Bonnie, Dirk Thomas, Jacob Perron, Michel Hidalgo, Sebastian Höffner, Stephen Brawnerrosidl_generator_dds_idlExpose .idl to DDS .idl conversion via rosidl translate CLI. (#55)Update maintainers. (#54)Contributors: Michel Hidalgo, Shane Loretzrosidl_generator_pyRemove dependency from rosidl_typesupport_connext_c (#127)Expose Python code generation via rosidl generate CLI (#123)remove maintainer (#126)Update maintainers (#119)Fix too early decref of WString when converting from Python to C (#117)Add pytest.ini so tests succeed locally. (#116)Contributors: Andrea Sorbini, Chris Lalancette, Claire Wang, Dirk Thomas, Michel Hidalgorosidl_parserUpdate and add package.xml descriptions to README (#553)Finish support for fixed-point literals.Fix parsing of small floats.Update the maintainers of this repository. (#536)Allow zero length string constants (#507)Add pytest.ini so tests succeed locally (#502)Contributors: Chris Lalancette, Dirk Thomas, Shane Loretzrosidl_runtime_cupdating quality declaration links (re:ros2/docs.ros2.org#52) (#581)Shorten some excessively long lines of CMake (#571)Update and add package.xml descriptions to README (#553)Fix item number in QD (#546)Update the maintainers of this repository. (#536)Add rcutils dependency. (#534)QD: Add links to hosted API docs (#533)Updated Quality Level to 1 (#532)Add benchmarks for rosidl_runtime_* packages (#521)Fix the declared language for a few packages (#530)Add fault injection macros and test (#509)Update rosidl_runtime_c QD to QL 2 (#500)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Louise Poubel, Scott K Logan, Shane Loretz, Stephen Brawner, brawner, shonigmannrosidl_runtime_cppupdating quality declaration links (re:ros2/docs.ros2.org#52) (#581)Fix typo of package name in README heading (#561)Update and add package.xml descriptions to README (#553)Fix item number in QD (#546)Update the maintainers of this repository. (#536)QD: Add links to hosted API docs (#533)Updated Quality Level to 1 (#532)Add benchmarks for rosidl_runtime_* packages (#521)Add to_yaml() function for C++ messages (#527)Add function for getting a types fully qualified name (#514)Fix misuses of input iterators in BoundedVector (#493)Update QD to reflect QL 2 statuses (#499)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Devin Bonnie, Dirk Thomas, Jacob Perron, Jonathan Wakely, Louise Poubel, Scott K Logan, Shane Loretz, Stephen Brawner, Tully Foote, shonigmannrosidl_runtime_pyAdd pytest.ini so local tests don’t display warning (#12)Contributors: Chris Lalancetterosidl_typesupport_cupdating quality declaration links (re:ros2/docs.ros2.org#52) (#108)Remove dependencies from Connext type support (#106)Expose C typesupport generation via rosidl generate CLI (#105)Typo typesupport_identidentifier (#103)Remove type_support_dispatch.cpp files. (#101)Defer path resolution of rosidl typesupport libraries to dynamic linker. (#98)Ensure typesupport handle functions do not throw. (#99)Explicitly check lib pointer for null (#95)Update Quality Declaration to QL 1 (#96)Add mock for rcutils_get_symbol failure (#93)Update the maintainers (#89)Catch exception from has_symbol (#86)Added benchmark test to rosidl_typesupport_c/cpp (#84)Handle rcpputils::find_library_path() failure (#85)Add fault injection macros and unit tests (#80)Remove rethrow in extern c code (#82)Add Security Vulnerability Policy pointing to REP-2006 (#76)Contributors: Alejandro Hernández Cordero, Andrea Sorbini, Chris Lalancette, Jose Luis Rivero, Jose Tomas Lorente, Louise Poubel, Michel Hidalgo, Shane Loretz, Stephen Brawner, shonigmannrosidl_typesupport_cppupdating quality declaration links (re:ros2/docs.ros2.org#52) (#108)Remove dependencies from Connext type support (#106)Expose C++ typesupport generation via rosidl generate CLI (#104)Remove type_support_dispatch.cpp files. (#101)Defer path resolution of rosidl typesupport libraries to dynamic linker. (#98)Ensure typesupport handle functions do not throw. (#99)Explicitly check lib pointer for null (#95)Update Quality Declaration to QL 1 (#96)Update the maintainers (#89)Added benchmark test to rosidl_typesupport_c/cpp (#84)Handle rcpputils::find_library_path() failure (#85)De-duplicate type_support_map.h header (#81)Add fault injection macros and unit tests (#80)Add Security Vulnerability Policy pointing to REP-2006 (#76)Contributors: Alejandro Hernández Cordero, Andrea Sorbini, Chris Lalancette, Jose Luis Rivero, Louise Poubel, Michel Hidalgo, Stephen Brawner, shonigmannrosidl_typesupport_fastrtps_cupdating quality declaration links (re:ros2/docs.ros2.org#52) (#69)Expose FastRTPS C typesupport generation via rosidl generate CLI (#65)Update QDs with up-to-date content (#64)Fix item number in QD (#59)Update QL to 2Update package maintainers (#55)Updat QD (#53)Fix invalid return on deserialize function (#51)Added benchmark test to rosidl_typesupport_fastrtps_c/cpp (#52)Update exec dependencies (#50)Add Security Vulnerability Policy pointing to REP-2006 (#44)QD Update Version Stability to stable version (#46)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jorge Perez, Louise Poubel, Michel Hidalgo, Stephen Brawner, shonigmann, sung-goo-kimrosidl_typesupport_fastrtps_cppupdating quality declaration links (re:ros2/docs.ros2.org#52) (#69)Expose FastRTPS C++ typesupport generation via rosidl generate CLI (#66)Update QDs with up-to-date content (#64)Fix item number in QD (#59)Update QL to 2Update package maintainers (#55)Update QD (#53)Add benchmark test to rosidl_typesupport_fastrtps_c/cpp (#52)Update exec dependencies (#50)Add Security Vulnerability Policy pointing to REP-2006 (#44)QD Update Version Stability to stable version (#46)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jorge Perez, Louise Poubel, Michel Hidalgo, Stephen Brawner, shonigmannrosidl_typesupport_interfaceupdating quality declaration links (re:ros2/docs.ros2.org#52) (#581)Fix item number in QD (#546)Update the maintainers of this repository. (#536)QD: Add links to hosted API docs (#533)Update Quality Declaration to QL 1 for rosidl_typesupport_interface (#519)Update QD to reflect QL 2 statuses (#499)Contributors: Chris Lalancette, Louise Poubel, Stephen Brawner, brawner, shonigmannrosidl_typesupport_introspection_cExpose C introspection typesupport generation via rosidl generate CLI (#572)Update the maintainers of this repository. (#536)Fix get_function and get_const_function semantics for arrays (#531)Fix the declared language for a few packages (#530)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Michel Hidalgo, Scott K Loganrosidl_typesupport_introspection_cppExpose C++ introspection typesupport generation via rosidl generate CLI (#573)Update the maintainers of this repository. (#536)Contributors: Chris Lalancette, Michel HidalgorpyutilsCreate a shared function for importing c libraries (#4)Add pytest.ini so local tests don’t display warning (#3)Contributors: Chris Lalancette, Emerson Knapprqt1.0.7 (#243)Remove Dirk from maintainers in package.xml files per request. (#236)Update maintainers for the crystal-devel branch (#234)Contributors: Michael Jeronimo, Scott K Loganrqt_actionUpdated Open Robotics maintainerFixed package to run with ros2 run (#8)Contributors: Alejandro Hernández Cordero, Mabel Zhangrqt_bagRemove an invalid import statement (#101)Reset timeline zoom after loading a new bag. (#98)Refactor the Rosbag2 class (#91)Fix exec_depend (#89)Use updated HistoryPolicy values to avoid deprecation warnings (#88)Enable recording for ROS2 (#87)Enable the playback functionality for ROS2 (#85)Port the topic and node selection dialogs to ROS2 (#86)Save the serialization format and offered_qos_profiles when exporting (#84)Enable the export/save bag functionality for ROS2 (#82)Update known message types and associated colors (#81)Open the bag directory instead of a single file (#80)Port the image_view plugin to ROS2 (#78)Clean up widgets in plot_view layout correctly (#69) (#77)Fix tuples for bisect calls (#67) (#76)Fix issue: no vertical scroll bar until window is resized (#63) (#75)Update the basic plugins for ROS2 (#72)Update the rosbag2 python module (#71)Dynamically resize the timeline when recording (#66)Starting point for resuming the ROS2 port (#70)Fix a bug with the status line progress bar (#62)Update a few minor status bar-related items (#61)Make the tree controls in the Raw View and Plot View consistent (#57)Update the package.xml files with the latest Open Robotics maintainers (#58)fix Python 3 issue: long/int (#52)save last directory opened to load a bag file (#40)fix shebang line for Python 3 (#48)bump CMake minimum version to avoid CMP0048 warningfix Python 3 exception, wrap filter call in list() (#46)add Python 3 conditional dependencies (#44)autopep8 (#30)add support for opening multiple bag files at once (#25)fix debug/warning messages for unicode filenames (#26)fix regression from version 0.4.10 (#17)fix regression from version 0.4.9 (#16)handle errors happening while loading a bag (#14)add rqt_bag.launch file (#440)fix Python 2 regression from version 0.4.4 (#424)use Python 3 compatible syntax (#421)fix race condition reading bag files (#412)add “From nodes” button to record mode (#348)show file size of bag file in the status bar (#347)fix mouse wheel delta in Qt 5 (#376)Support Qt 5 (in Kinetic and higher) as well as Qt 4 (in Jade and earlier) (#359)fix publishing wrong topic after scrolling (#362)RQT_BAG: Ensure monotonic clock publishing. Due to parallelism issues, a message can be published with a simulated timestamp in the past. This lead to undesired behaviors when using TF for example.Added step-by-step playback capabilityfix viewer plugin relocation issue (#306)fix topic type retrieval for multiple bag files (#279)fix region_changed signal emission when no start/end stamps are setimprove right-click menuimprove popup management (#280)implement recording of topic subsetssort the list of topicsupdate plugin scripts to use full name to avoid future naming collisionsfix visibility with dark Qt theme (#263)fix compatibility with Groovy, use queue_size for Python publishers only when available (#243)use thread for loading bag files, emit region changed signal used by plotting plugin (#239)export architecture_independent flag in package.xml (#254)fix closing and reopening topic viewsuse queue_size for Python publishersfix raw view not showing fields named ‘msg’ (#226)add option to publish clock tim from bag (#204)add groups for rqt plugins, renamed some plugins (#167)fix high cpu load when idle (#194)update rqt_bag plugin interface to work with qt_gui_core 0.2.18fix rendering of icons on OS X (ros-visualization/rqt#83)fix shutdown of plugin (#31)fix saving parts of a bag (#96)fix long topic names (#114)fix zoom behavior (#76)Fix; skips time when resuming playback (#5)Fix; timestamp printing issue (#6)expose command line arguments to rqt_bag scriptadded fix to set play/pause button correctly when fastforwarding/rewinding, adjusted time headers to 0m00s instead of 0:00m for ease of readingsupport passing bagfiles on the command line (currently behind –args)first release of this package into GroovyContributors: Aaron Blasdel, Chris Lalancette, Michael Grupp, Michael Jeronimo, lsouchet, sambroserqt_bag_pluginsRefactor the Rosbag2 class (#91)Port the plot view to ROS2 (#79)Port the image_view plugin to ROS2 (#78)Starting point for resuming the ROS2 port (#70)Make the tree controls in the Raw View and Plot View consistent (#57)Update the package.xml files with the latest Open Robotics maintainers (#58)initialize pil_mode when image is compressed (#54)support 16-bit bayer images (#45)maintain image aspect ratio (#32)fix Python 3 issue: long/int (#51)fix Python 3 issue: ensure str is encoded before decoding (#50)bump CMake minimum version to avoid CMP0048 warningadd Python 3 conditional dependencies (#44)add cairocffi as the fallback module (#43)autopep8 (#30)fix Python 2 regression from version 0.4.4 (#426)use Python 3 compatible syntax (#421)fix crash when toggling thumbnail (#380)lock bag when reading for plotting (#382)Support Qt 5 (in Kinetic and higher) as well as Qt 4 (in Jade and earlier) (#359)add missing dependency on rqt_plot (#316)work around Pillow segfault if PyQt5 is installed (#289,#290)add displaying of depth image thumbnailsadd missing dependency on python-cairo (#269)fix missing installation of resource subfolderadd plotting plugin (#239)fix rqt_bag to plot array members (#253)export architecture_independent flag in package.xml (#254)fix PIL/Pillow error (#224)first release of this package into GroovyContributors: John Stechschulte, Michael Jeronimorqt_consoleUse underscores in setup.cfg instead of dashes (#31)Fix regression introduced in#21(#28)Changed the build type to ament_python and added setup.cfg (#21)Contributors: Alejandro Hernández Cordero, Michel Hidalgorqt_graphMake topics that have qos incompatibilities red in the graph, add information to the node tooltip (#61)Add node name, topic name, and endpoint kind to the qos edge tooltip (#60)Update maintainers for ROS2 branches (#55)add edge tooltip with QoS of publishers and subscribers (#53)install executable rqt_graph (#49)add setup.cfg with script install directories (#42)add pytest.ini so local tests don’t display warning (#48)Contributors: Ivan Santiago Paunovic, Michael Jeronimorqt_guigetiterator() renamed to iter() in Python 3.9 (#239)Contributors: goekcerqt_gui_cppuse tgt compile features (#247)Contributors: Audrow Nashrqt_gui_pyFix a crash at shutdown (#248)Contributors: Michael Jeronimorqt_msgChanged the build type to ament_python and fixed package to run with ros2 run (#8)Use rosidl_runtype_py instead of message_helpers where possible (#11)Contributors: Alejandro Hernández Cordero, Ivan Santiago Paunovicrqt_plotChanged the build type to ament_python and fixed package to run with ros2 run (#58)Fix plots of array items (#71)Update maintainersContributors: Alejandro Hernández Cordero, Ivan Santiago Paunovic, Mabel Zhangrqt_publisherChanged the build type to ament_python and fixed package to run with ros2 run (#18)Drop numpy.float128 references (#26)Use rosidl_runtime_py instead of rqt_py_common where possible (#24)Add now() to evaluation (#22)fix setting expressions on sequence items (#16)Contributors: Alejandro Hernández Cordero, Ivan Santiago Paunovic, Michel Hidalgo, Yossi Ovcharikrqt_py_commonAvoid installing test interfaces (#228)Contributors: Dirk Thomasrqt_py_consoleChanged the build type to ament_python and fixed package to run with ros2 run (#8)Contributors: Alejandro Hernández Corderorqt_reconfigureCleanups to the install scripts. (#103)Fix a flake8 warning. (#99)Use timeouts in service calls to avoid hangs (#98)Add maintainer to package.xml (#95)Save instance state in rqt settings (#90)Use safe YAML loader (#89)Don’t process scroll events unless specifically focused (#88)Fix node selection from command line (#87)Add pytest.ini so local tests don’t display warning (#91)Support PEP 338 invocation of rqt_reconfigure (#85)Fixed package to run with ros2 run (#81)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michael Jeronimo, Scott K Loganrqt_service_callerChanged the build type to ament_python and fixed package to run with ros2 run (#13)ignore services that don’t use the SRV_MODE (‘srv’) (#20)Contributors: Alejandro Hernández Cordero, William Woodallrqt_shellChanged the build type to ament_python and fixed package to run with ros2 run (#11)Contributors: Alejandro Hernández Corderorqt_srvChanged the build type to ament_python and fixed package to run with ros2 run (#4)Contributors: Alejandro Hernández Corderorqt_topChanged the build type to ament_python and fixed package to run with ros2 run (#8)Contributors: Alejandro Hernández Corderorqt_topicAdd pytest.ini to silence warnings when running locally.Fix warnings pointed out by flake8.Created an entry-point for rqt_topic in setup.py (#16)Fix flake8 errors and add linter tests (#28)Update Open Robotics Maintainer (#26)Use raw / non-string value for ordering (#23)Support order fields as defined in message (#22)Fix the type cell value for sequence items (#21)Updated version package and license in setup.py (#17)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Dirk Thomas, Scott K Loganrti_connext_dds_cmake_modulePass-Wl,--no-as-neededfor system dependencies of Connext 5.3.1.SetIMPORTED_NO_SONAMEtruefor Connext 5.3.1 imported library target.Addforament_cmake.Addforrti-connext-dds-5.3.1Add dependency from rti-connext-dds-5.3.1.Initial release.rttestFix up nonsensical handling of NULL in rttest_get_{params,statistics} (#107)Remove “struct” from rttest_sample_buffer variable declaration. (#105)Convert the sample buffer to a vector. (#104)Use strdup instead of strlen/strcpy dance. (#100)Enable basic warnings in rttest (#99)Only copy an rttest_sample_buffer if it is not nullptr. (#98)Convert timespec to uint64 not long and vice versa (#94) (#96)Fix standard deviation overflow(#95) (#97)Contributors: Audrow Nash, Chris Lalancette, y-okumura-isprviz2Use “%s” as format string literal in logging macros (#633)Add linters and use ament_lint_auto (#608)Update maintainers (#607)Move and update documentation for ROS 2 (#600)Contributors: Audrow Nash, Chris Lalancette, Jacob Perronrviz_assimp_vendorAlways preserve source permissions in vendor packages (#647)Add an override flag to force vendored build (#642)Add linters and use ament_lint_auto (#608)Update maintainers (#607)Updated a hack to avoid CMake warning with assimp 5.0.1 and older, applying it cross platforms (#565)Contributors: Dirk Thomas, Jacob Perron, Scott K Loganrviz_commonAdd visualization_frame to the public API (#660)Add ViewPicker::get3DPatch to the public API (#657)Fix byte indexing for depth patch pixels (#661)fix toolbar vanishing when pressing escape (#656)Expose VisualizationManager and YamlConfigReader to the public API (#649)Use the stack for the classes in the property test. (#644)Check that the views_man_ and views_man_->getCurrent() are not nullptr. (#634)Fix for mousewheel to zoom in/out (#623)Ensure rviz_common::MessageFilterDisplay processes messages in the main thread (#620)Fix render window disppearing after saving image (#611)Add linters and use ament_lint_auto (#608)Update maintainers (#607)TimePanel port (#599)Upgrade to tinyxml2 for rviz (#418)Fix segfault on changing filter size for non-existent topic (#597)improve color support for themes (#590)Fix topic IntProperty number ranges (#596)Switch to nullptr everywhere. (#592)Expose MessageFilterDisplay’s queue size (#593)Filter topics in drop down menu (#591)rviz_common: Remove variadic macro warning check (#421)Use retriever.hpp (#589)Fix the order of destructors (#572)Changed to not install test header files in rviz_rendering. (#564)Fixed alphabetical include order (#563)Changed to avoid trying to moc generateenv_config.hppfile. (#550)Contributors: Audrow Nash, Chen Lihui, Chris Lalancette, Jacob Perron, Jafar Abdi, Joseph Schornak, Karsten Knese, Martin Idel, Michael Ferguson, Michael Jeronimo, Michel Hidalgo, Nico Neumann, Rich Mattes, Shane Loretz, ipa-fez, spiralrayrviz_default_pluginsAdd ViewPicker::get3DPatch to the public API (#657)Allow to zoom more with orbit controller (#654)Fix possible nullptr access in robot_joint.cpp. (#636)Fix for mousewheel to zoom in/out (#623)Make the types explicit in quaternion_helper.hpp. (#625)Update status message by removing colon or adjust colon position (#624)Do not use assume every RenderPanel has a ViewController. (#613)Add linters and use ament_lint_auto (#608)Update maintainers (#607)TimePanel port (#599)Upgrade to tinyxml2 for rviz (#418)Use retriever.hpp (#589)Added covariance settings to set pose estimate (#569)use reference in range loops to avoid copy (#577)Changed to not install test header files in rviz_rendering. (#564)Changed to use a dedicated TransformListener thread. (#551)Suppressed warnings when building with older Qt versions. (#562)Restored compatibility with older Qt versions (#561)Contributors: Chen Lihui, Chris Lalancette, Dirk Thomas, Jacob Perron, Joseph Schornak, Martin Idel, Matthijs den Toom, Michel Hidalgo, Nico Neumann, Shane Loretz, Victor Lamoine, ymd-stellarviz_ogre_vendorAlways preserve source permissions in vendor packages (#647)Add linters and use ament_lint_auto (#608)Update maintainers (#607)Pass through CMAKE_{C,CXX}_FLAGS to OGRE build (#587)Contributors: Jacob Perron, Scott K Loganrviz_renderingreset current line width when calculating text width (#655)Silence a dead store warning. (#643)Fix a memory leak when using the ResourceIOSystem. (#641)Revert “Support loading meshes other than .mesh and .stl with package URIs (#610)” (#638)Prevent rviz_rendering::AssimpLoader from loading materials twice. (#622)Support loading meshes other than .mesh and .stl with package URIs (#610)Add linters and use ament_lint_auto (#608)Update maintainers (#607)Switch to nullptr everywhere. (#592)Use retriever.hpp (#589)Avoid hidding base class getRenderOperation in PointCloudRenderable (#586)Changed to not install test header files in rviz_rendering. (#564)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgo, Shane Loretz, ipa-fezrviz_rendering_testsAdd linters and use ament_lint_auto (#608)Update maintainers (#607)Use retriever.hpp (#589)Changed to not install test header files in rviz_rendering. (#564)Contributors: Chris Lalancette, Jacob Perron, Shane Loretzrviz_visual_testing_frameworkQuiet a clang warning about a Qt memory leak. (#651)use rcutils_get_env. (#609)Add linters and use ament_lint_auto (#608)Update maintainers (#607)Contributors: Chris Lalancette, Jacob Perron, tomoyasensor_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Fix PointCloud2Iterator namespacing in docs (#139)Add coverage/performance to qd for sensor_msgs (#137)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Missing cstring header for memcpy in fill_image.hpp (#126)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Andre Nguyen, Chris Lalancette, Jose Luis Rivero, Michel Hidalgo, Stephen Brawner, brawner, shonigmannsensor_msgs_pyUse underscores instead of dashes in setup.cfg (#150)Port of point_cloud2.py from ROS1 to ROS2. As seperate pkg. (#128)Contributors: Ivan Santiago Paunovic, Sebastian Gransshape_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannshared_queues_vendorExplicitly add emersonknapp as maintainer (#692)Update the package.xml files with the latest Open Robotics maintainers (#535)Contributors: Emerson Knapp, Michael Jeronimospdlog_vendorupdating quality declaration links (re:ros2/docs.ros2.org#52) (#24)Update to spdlog 1.8.2 (#23)Remove a stale TODO (#22)Always preserve source permissions in vendor packages (#20)Remove unnecessary call to find_package(PATCH) (#18)Updated QD to 1 (#16)bump spdlog version to 1.6.1 (#15)Bump QD to level 3 and updated QD (#14)Add Security Vulnerability Policy pointing to REP-2006. (#13)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Dirk Thomas, Scott K Logan, shonigmannsqlite3_vendorExplicitly add emersonknapp as maintainer (#692)Always preserve source permissions in vendor packages (#645)Update the package.xml files with the latest Open Robotics maintainers (#535)use interface_include_directories (#426)Contributors: Emerson Knapp, Karsten Knese, Michael Jeronimo, Scott K Logansros2Skip mypy test on platforms using importlib_resources (#258)Enable topic “ros_discovery_info” for rmw_connextdds (#253)Declare missing dependency on python3-importlib-resources (#249) Co-authored-by: Fix namedtuple names. (#250)parameter_events topic is now absolute (#233) Signed-off-by: Mikael Arguedas Expose keystore operations in public API (#241)add cyclonedds to the list of rmw using graph info topics (#231)Add scope parameter (#230)Fix name of argument passed to NodeStrategy (#227)Remove the use of pkg_resources. (#225)Make use of ros_testing to test policy generation. (#214)Add pytest.ini so local tests don’t display warning (#224)Fix list keys verb (#219)Contributors: Andrea Sorbini, Chris Lalancette, Jacob Perron, Jose Luis Rivero, Kyle Fazzari, Michel Hidalgo, Mikael Arguedas, Scott K Loganstatistics_msgsUpdating Quality Declaration (#120)Update quality declaration to QL 1. (#116)Update package maintainers. (#112)Increase Quality level of packages to 3 (#108)Add Security Vulnerability Policy pointing to REP-2006. (#106)Updating QD to reflect package versions (#107)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannstd_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145) Co-authored-by: Simon Honigmann Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannstd_srvsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannstereo_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmanntango_icons_vendorAdd exec_depend on tango-icon-theme system package (#8)Added common linters (#7) * Added common linters * Fixed license in package.xmlRemaned package qt_gui_icons -> tango_icons_vendor (#4) * Remaned package qt_gui_icons -> tango_icons_vendor * Updated CMake var to install tango icons: INSTALL_TANGO_ICONS * Added cmake option INSTALL_TANGO_ICONS * Fixed logic * set INSTALL_TANGO_ICONS_DEFAULT_VALUE to option * Make linters happyUpdated link on the description (#6)Updated the maintainer (#5)Version 0.0.0 this package was never released (#3)Install icons by default on macOS too (#1)Updating package.xmlfixup! Install tango iconsAdding iconsInstall tango iconsContributors: Alejandro Hernández Cordero, Scott K Logan, Stephen, Stephen Brawnertest_cliUpdate maintainers. (#450)Enable -Wall, -Wextra, and -Wpedantic. (#447)Contributors: Audrow Nash, Jacob Perrontest_cli_remappingFix test_cli_remapping flaky test. (#470)Update maintainers. (#450)Enable -Wall, -Wextra, and -Wpedantic. (#448)Contributors: Audrow Nash, Jacob Perron, Shane Loretztest_communicationAdd support for rmw_connextdds. (#463)Kill off the ros2 daemon before running tests. (#460)Remove Opensplice from test_communication. (#460)Make TestMessageSerialization robust to missed messages. (#456)Add corresponding rclcpp::shutdown. (#455)Update maintainers. (#450)Contributors: Andrea Sorbini, Chris Lalancette, Jacob Perron, Stephen Brawnertest_interface_filesUpdate maintainer (#13)Contributors: Jacob Perrontest_launch_rosAdd a package marker to test_launch_ros. (#226)Re-order shutdown vs node destruction (#213)Increase test_composable_node_container timeout (#195)Remove constructors arguments deprecated since Foxy (#190)Merge pull request#183from ros2/update-maintainersMove previous maintainer to Update the package.xml files with the latest Open Robotics maintainersHandle any substitution types for SetParameter name argument (#182)Address security bug in yaml loading (#175)Resolve TODO in test (#172)Fix case where list of composable nodes is zero (#173)Do not use event handler for loading composable nodes (#170)Fix race with launch context changes when loading composable nodes (#166)Substitutions in parameter files (#168)Fix problems when parsing aCommandSubstitutionas a parameter value (#137)Drop double single-quoted params. (#164)Add a way to set remapping rules for all nodes in the same scope (#163)Fix ComposableNode ignoring PushRosNamespace actions (#162)Add a SetParameter action that sets a parameter to all nodes in the same scope (#158)Make namespace parameter mandatory in LifecycleNode constructor (#157)Avoid using a wildcard to specify parameters if possible (#154)Remove the loop parameter from async.sleep. (#155)Fix no specified namespace (#153)Fix test_node_frontend (#146)Add pytest.ini so local tests don’t display warning (#152)Contributors: Chris Lalancette, Dan Rose, Ivan Santiago Paunovic, Jacob Perron, Michael Jeronimo, Michel Hidalgo, Scott K Logan, Víctor Mayoral Vilchestest_launch_testingUpdate package maintainers (#465)Add pytest.ini to test_launch_testing so tests succeed locally. (#431)Contributors: Chris Lalancette, Michel Hidalgotest_msgsUpdate package maintainers. (#112)Contributors: Chris Lalancettetest_quality_of_serviceAdd support for rmw_connextdds. (#463)Run QoS tests. (#441)Update maintainers. (#450)Contributors: Andrea Sorbini, Jacob Perron, Michel Hidalgotest_rclcppReenable test that used to be flaky. (#467)Get_parameters_service_ should return empty if allow_undeclared_ is false. (#466)Make test pass after rclcpp#1532. (#465)Adapt tests to statically typed parameters. (#462)Guard against TOCTTOU with rclcpp::ok and rclcpp:spin_some. (#459)Update parameter client test with timeout. (#457)Call rclcpp::init and rclcpp::shutdown in each test for test_rclcpp. (#454)Set cppcheck timeout to 400 seconds. (#453)Modify to match Waitable interface adding take_data. (#444)Update maintainers. (#450)Fix rclcpp timeout subscriber test. (#440) * Use nonzero lower bound for timeout checks. * Relax time tolerance.Show numbers of nanseconds in EXPECT with durations. (#438) * Show numbers of nanseconds in expect with durations * Fix syntaxRemove ament_pytest dependency from test_rclcpp. (#437) It is not used in test_rclcpp anywhere.Contributors: Audrow Nash, Chris Lalancette, Dirk Thomas, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgo, Shane Loretz, Stephen Brawner, Tomoya Fujita, tomoyatest_rmw_implementationImplement test for subscription loaned messages (#186)Remove rmw_connext_cpp. (#183)Add support for rmw_connextdds (#182)Add function for checking QoS profile compatibility (#180)Make sure to initialize the rmw_message_sequence after init. (#175)Set the value of is_available before entering the loop (#173)Set the return value of rmw_ret_t before entering the loop. (#171)Add some additional checking that cleanup happens. (#168)Add test to check rmw_send_response when the client is gone (#162)Update maintainers (#154)Add fault injection tests to construction/destroy APIs. (#144)Add tests bad type_support implementation (#152)Add tests for localhost-only node creation (#150)Added rmw_service_server_is_available tests (#140)Use 10x the intraprocess delay to wait for sent requests. (#148)Added rmw_wait, rmw_create_wait_set, and rmw_destroy_wait_set tests (#139)Add tests service/client request/response with bad arguments (#141)Added test for rmw_get_serialized_message_size (#142)Add service/client construction/destruction API test coverage. (#138)Added rmw_publisher_allocation and rmw_subscription_allocation related tests (#137)Add tests take serialized with info bad arguments (#130)Add gid API test coverage. (#134)Add tests take bad arguments (#125)Bump graph API test coverage. (#132)Add tests take sequence serialized with bad arguments (#129)Add tests take sequence + take sequence with bad arguments (#128)Add tests take with info bad arguments (#126)Add tests for non-implemented rmw_take_* functions (#131)Add tests publish serialized bad arguments (#124)Add tests publish bad arguments (#123)Add tests non-implemented functions + loan bad arguments (#122)Add missing empty topic name tests. (#136)Add rmw_get_serialization_format() smoke test. (#133)Complete publisher/subscription QoS query API test coverage. (#120)Remove duplicate assertions (#121)Add publisher/subscription matched count API test coverage. (#119)Add serialize/deserialize API test coverage. (#118)Add subscription API test coverage. (#117)Extend publisher API test coverage (#115)Add node construction/destruction API test coverage. (#112)Check that rmw_init() fails if no enclave is given. (#113)Add init options API test coverage. (#108)Complete init/shutdown API test coverage. (#107)Add dependency on ament_cmake_gtest (#109)Add test_rmw_implementation package. (#106)Contributors: Alejandro Hernández Cordero, Andrea Sorbini, Chris Lalancette, Geoffrey Biggs, Ivan Santiago Paunovic, Jacob Perron, Jose Tomas Lorente, José Luis Bueno López, Michel Hidalgo, Miguel Company, Shane Loretztest_securityAdd support for rmw_connextdds. (#463)Update deprecated gtest macros. (#449)Update maintainers. (#450)Run test_security on CycloneDDS as well. (#408)Remove invalid cert folder to force regeneration of certificates. (#434)Contributors: Andrea Sorbini, Audrow Nash, Jacob Perron, Mikael Arguedastest_tf2Update maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Fix a TOCTTOU race in tf2. (#307)Fixed memory leak in Buffer::waitForTransform (#281)relax test timings to pass with Connext (#304)Explicitly initialize instances of tf2::Duration (#291)Generate callbacks after updating message_ (#274)fix test_static_publisher in macos (#284)Fix up the dependencies in test_tf2. (#277)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Dirk Thomas, Ivan Santiago Paunovic, Martin Ganeff, Michael Carroll, ymd-stellatf2Change index.ros.org -> docs.ros.org. (#394)Update maintainers of the ros2/geometry2 fork. (#328)Active usual compiler warnings in tf2 (#322)Cleanups in buffer_core.cpp. (#301)Add PoseWithCovarianceStamped transform support (#312)Fix a TOCTTOU race in tf2. (#307)Fixed memory leak in Buffer::waitForTransform (#281)Add common linters to tf2. (#258)Provide more available error messaging for nonexistent and invalid frames in canTransform (ros2 #187)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Ivan Santiago Paunovic, Joshua Whitley, Martin Ganefftf2_bulletUpdate maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Suppress compiler warning on Centos (#290)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Michael Carrolltf2_eigenFix linter errors (#385)Fix up the style in tf2_eigen. (#378)Fix doTransform with Eigen Quaternion (#369)Update maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Contributors: Audrow Nash, Bjar Ne, Chris Lalancette, Ivan Santiago Paunovictf2_eigen_kdlfix order of find eigen3_cmake_module & find eigen3 (#344)Update package.xml (#333)Port eigen_kdl.h/cpp to ROS2 (#311)Contributors: Ahmed Sobhy, Jafar Abditf2_geometry_msgsFix doTransform with Eigen Quaternion (#369)Update maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Add PoseWithCovarianceStamped transform support (#312)Don’t install python tf2_geometry_msgs (#299) It hasn’t been ported yet. Closeshttps://github.com/ros2/geometry2/issues/285Split tf2_ros in tf2_ros and tf2_ros_py (#210) * Split tf2_ros in tf2_ros and tf2_ros_pyContributors: Alejandro Hernández Cordero, Bjar Ne, Chris Lalancette, Ivan Santiago Paunovic, Joshua Whitley, Shane Loretztf2_kdlUpdate maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Ivan Santiago Paunovictf2_msgsUpdate maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Contributors: Chris Lalancette, Ivan Santiago Paunovictf2_pyAdapt to Python 3.9 (#362)Update maintainers of the ros2/geometry2 fork. (#328)Add in pytest.ini so tests succeed locally. (#280)Contributors: Chris Lalancette, Homalozoa Xtf2_rosGuard against access to null node pointer (#393)Allow to reconfigure durability for /tf topic broadcaster/listener (#383)Fix the rcl type used in the time jump. (#391)Fix linter errors (#385)fix accessing freed resources (#386)Allow reconfiguring qos of tf and tf_static topics through parameters (#381)Replace ROS_* logging macros and use RCLCPP_* instead (#380)Improve message filters error messages (#364)Clarify the role of child_frame_id and header.frame_id in the documentation. (#345)Remove usage of deprecated rclcpp::Duration constructor (#340)Remove messages_count member from tf2_ros::MessageFilter. (#335)Style fixup in tf2_ros. (#325)Update maintainers of the ros2/geometry2 fork. (#328)Update goal response callback signature (#323)Activate usual compiler warnings and fix errors (#270)Fixed memory leak in Buffer::waitForTransform (#281)fix time-reset test with Connext (#306)reenable FrameGraph server (#198)Use the usual style of parameters for static_transform_program (#300)Make static_transform_broadcaster consistent with its command line description (#294)Avoid using invalid std::list iterators (#293)Generate callbacks after updating message_ (#274)Moved unique_lock of messages_mutex_ to guarantee pointer (#279)Fix dependencies in tf2_ros. (#269)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Dirk Thomas, Hunter L. Allen, Ivan Santiago Paunovic, Jacob Perron, Kazunari Tanaka, Martin Ganeff, Michael Carroll, Vikas Dhiman, ymd-stellatf2_ros_pyUse underscores instead of dashes in setup.cfg. (#403) (#404)Use global namespace for TransformListener topics (#390)Fix indentation of a comment in buffer.py (#371)Update rclpy.Rate TODO with url to issue (#324)Update maintainers of the ros2/geometry2 fork. (#328)Add deprecation warnings to lookup_transform to handle the passing of the incorrect Time object. (#319)change signature to show true arguments (#321)Handle when None passed to qos argument in the constructor of TransformBroadcaster. (#320)Add type hints to tf2_ros_py code(#275) (#315)Clear callbacks_to_remove variable after removing (#303)Fix cache_time None check in buffer.py (#297)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jacob Perron, Matthijs den Toom, ScottMcMichael, surfertastf2_sensor_msgsUpdate maintainers of the ros2/geometry2 fork. (#328)Activate usual compiler warnings and fix errors (#270)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Ivan Santiago Paunovictf2_toolsUse underscores instead of dashes in setup.cfg. (#403) (#404)Add wait time option to view_frames (#374)Cleanup tf2_tools to be more modern. (#351)Update maintainers of the ros2/geometry2 fork. (#328)Address security bug in yaml loading (#313)Split tf2_ros in tf2_ros and tf2_ros_py (#210)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jacob Perron, Víctor Mayoral VilchestlsfSwitch to standard __VA_ARGS__. (#9)Enable basic warnings (#8)Contributors: Audrow Nash, Chris Lalancettetlsf_cppAdd in the Apache license to tlsf_cpp. (#108)Contributors: Chris Lalancettetopic_monitorUse is_alive for threads. (#510) (#513)Use underscores instead of dashes in setup.cfg (#502)Change index.ros.org -> docs.ros.org. (#496)Update deprecated qos policy value names (#468)Update the package.xml files with the latest Open Robotics maintainers (#466)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Michael Jeronimotopic_statistics_demoChange index.ros.org -> docs.ros.org. (#496)Update logging macros (#476)Update the package.xml files with the latest Open Robotics maintainers (#466)Create new topic statistics demo package (#454)Contributors: Audrow Nash, Chris Lalancette, Michael Jeronimo, Prajakta GokhaletracetoolsUpdate QD to be more specific about public APINamespace tracetools C++ functions and macros and deprecate current onesAdd support for rcl_publish and rclcpp_publish tracepointsAdd instrumentation support for linking a timer to a nodeBring tracetools up to quality level 1Add lifecycle node state transition instrumentationDo not export tracetools if emptyAllow disabling tracetools status appContributors: Christophe Bedard, Ingo Lütkebohle, José Antonio Moraltracetools_launchAllow configuring tracing directory through environment variablesContributors: Christophe Bedardtracetools_testUpdate after namespacing C++ tracetools functions and macrosAdd tests for rcl_publish and rclcpp_publish tracepointsAllow asserting order of list of eventsAllow skipping test trace cleanup by setting an environment variableAdd test for timer-node linking instrumentationIncreased code coverage > 94% as part of QL1Add lifecycle node state transition instrumentation testContributors: Alejandro Hernández Cordero, Christophe Bedard, Ingo Lütkebohletracetools_traceAdd support for rcl_publish and rclcpp_publish tracepointsFix flake8 blind except error by using more concrete typesAllow configuring tracing directory through environment variablesCleanly stop ros2trace/tracetools_trace tracing on SIGINTAdd instrumentation support for linking a timer to a nodeAdd lifecycle node state transition instrumentationContributors: Christophe Bedard, Ingo Lütkebohletrajectory_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Finish up API documentation (#123)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannturtlesimIgnore key up events in teleop_turtle_key on Windows (#118)Update maintainers (#106)Update goal response callback signature (#100)add holonomic motion for turtlesim (#98)add step value to turtlesim color parameters (#91)update Foxy turtle (#90)Contributors: Jacob Perron, Michel Hidalgo, Shane Loretzunique_identifier_msgsChange index.ros.org -> docs.ros.org (#21)Update QD to QL 1 (#17)Update Quality Declaration to QL2. (#15)Update Quality level to level 3 (#13)Add Security Vulnerability Policy pointing to REP-2006. (#11)Contributors: Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawnerurdfWork around Windows min/max bug. (#21)Enable -Wall -Wextra -Wpedantic (#20)Add dependency on TinyXML2 (#19)Remove TinyXML dependency from urdf. (#17)Make urdf plugable and revive urdf_parser_plugin (#13)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzurdf_parser_pluginExport urdfdom_headers as urdf_parser_plugin dependency. (#25)Make urdf plugable and revive urdf_parser_plugin (#13)Contributors: Michel Hidalgo, Shane Loretzvisualization_msgsChange index.ros.org -> docs.ros.org. (#149)updating quality declaration links (re:ros2/docs.ros2.org#52) (#145)Update QDs to QL 1 (#135)Update package maintainers. (#132)Updated Quality Level to 2 (#131)Update Quality levels to level 3 (#124)Add Security Vulnerability Policy pointing to REP-2006. (#120)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Michel Hidalgo, Stephen Brawner, brawner, shonigmannyaml_cpp_vendorAlways preserve source permissions in vendor packages (#22)Add an override flag to force vendored build (#21)Reapply “Use system installed yaml-cpp 0.6 if available (#8)” (#16)Revert “Use system installed yaml-cpp 0.6 if available (#8)” (#15)Use system installed yaml-cpp 0.6 if available (#8)Contributors: Ivan Santiago Paunovic, Scott K Logan, Sean Yenzstd_vendorExplicitly add emersonknapp as maintainer (#692)Always preserve source permissions in vendor packages (#645)Zstd should not install internal headers - some of them try include others that aren’t installed. We don’t use them. Avoid the situation (#631)Patch zstd 1.4.4 to include cmake_minimum_version bump to 2.8.12 (#579)Update the package.xml files with the latest Open Robotics maintainers (#535)Contributors: Emerson Knapp, Michael Jeronimo, Scott K Logan \ No newline at end of file diff --git "a/exported_docs/ros2/Gazebo\357\203\201.txt" "b/exported_docs/ros2/Gazebo\357\203\201.txt" new file mode 100644 index 0000000..ccbebe9 --- /dev/null +++ "b/exported_docs/ros2/Gazebo\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Gazebo +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Gazebo/Simulation-Gazebo.html +Section: Installation +-------------------------------------------------------------------------------- + +GazeboThis set of tutorials will teach you how to configure the Gazebo simulator with ROS 2.Setting up a robot simulation (Gazebo) \ No newline at end of file diff --git "a/exported_docs/ros2/Glossary\357\203\201.txt" "b/exported_docs/ros2/Glossary\357\203\201.txt" new file mode 100644 index 0000000..b9f285f --- /dev/null +++ "b/exported_docs/ros2/Glossary\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: Glossary +URL: https://docs.ros.org/en/jazzy/Glossary.html +Section: Installation +-------------------------------------------------------------------------------- + +GlossaryGlossary of terms used throughout this documentation:APIAn API, or Application Programming Interface, is an interface that is provided by an “application”, which in this case is usually a shared library or other language appropriate shared resource. APIs are made up of files that define a contract between the software using the interface and the software providing the interface. These files typically manifest as header files in C and C++ and as Python files in Python. In either case it is important that APIs are grouped and described in documentation and that they are declared as either public or private. Public interfaces are subject to change rules and changes to the public interfaces prompt a new version number of the software that provides them.client_libraryA client library is anAPIthat provides access to the ROS graph using primitive middleware concepts like Topics, Services, and Actions.packageA single unit of software, including source code, build system files, documentation, tests, and other associated resources.REPROS Enhancement Proposal. A document that describes an enhancement, standardization, or convention for the ROS community. +The associated REP approval process allows the community to iterate on a proposal until some consensus has been made, at which point it can be ratified and implemented, which then becomes documentation. +All REPs are viewable from theREP index.VCSVersion Control System, such as CVS, SVN, git, mercurial, etc…rclcppThe C++ specificClient Libraryfor ROS. This includes any middleware related APIs as well as the related message generation of C++ data structures based on interface definitions like Messages, Services, and Actions.repositoryA collection of packages usually managed using aVCSlike git or mercurial and usually hosted on a site like GitHub or BitBucket. +In the context of this document, repositories usually contain one or morepackagesof one type or another. \ No newline at end of file diff --git "a/exported_docs/ros2/GurumNetworks_GurumDDS\357\203\201.txt" "b/exported_docs/ros2/GurumNetworks_GurumDDS\357\203\201.txt" new file mode 100644 index 0000000..bc4a71a --- /dev/null +++ "b/exported_docs/ros2/GurumNetworks_GurumDDS\357\203\201.txt" @@ -0,0 +1,34 @@ +Title: GurumNetworks GurumDDS +URL: https://docs.ros.org/en/jazzy/Installation/DDS-Implementations/Working-with-GurumNetworks-GurumDDS.html +Section: Installation +-------------------------------------------------------------------------------- + +GurumNetworks GurumDDSrmw_gurumddsis an implementation of the ROS middleware interface using GurumNetworks GurumDDS. For more information about GurumDDS, visit theGurumNetworks website.PrerequisitesThis guide assumes you have completed the ROS 2 environment setup process, either byInstalling ROS 2 via Deb PackagesorBuilding ROS 2 from source on Ubuntu.Version Requirements (see the README for details):ROS 2 DistroGurumDDS Versionrolling>= 3.2.0jazzy>= 3.2.0humble3.1.xDeb packages of GurumDDS are provided in the ROS 2 apt repositories on Ubuntu. +Windows binary installer of GurumDDS will be available soon.You can obtain a free trial license from theGurumDDS Free Trial page.After acquiring a license, place it in the following location:/etc/gurumnetInstallationOption 1: Install from the ROS 2 apt repository (Recommended)sudoaptinstallros-jazzy-rmw-gurumdds-cppThis installs bothrmw_gurumdds_cppandgurumdds.Option 2: Build from source codeClone the repositorycdros2_ws/src +gitclonehttps://github.com/ros2/rmw_gurumdds-bjazzyros2/rmw_gurumddsInstall dependencies:cd.. +rosdepinstall--fromsrc-i--rosdistrojazzyBuild the worksapce using Colcon:colconbuild--symlink-installSwitch to rmw_gurumddsSwitch from other RMW implementations to rmw_gurumdds by setting the environment variable:exportRMW_IMPLEMENTATION=rmw_gurumdds_cppFor more information on working with multiple RMW implementations, seeWorking with multiple RMW implementations.Testing the installationRun thetalkerandlistenernodes to verify your installation:ros2rundemo_nodes_cpptalkerros2rundemo_nodes_cpplistenerIf the nodes communicate successfully, your installation is working correctly.NoteRemember to source your ROS 2 setup script before running these commands. + +Code Examples: + +Language: unknown +sudoaptinstallros-jazzy-rmw-gurumdds-cpp + +Language: unknown +cdros2_ws/src +gitclonehttps://github.com/ros2/rmw_gurumdds-bjazzyros2/rmw_gurumdds + +Language: unknown +cd.. +rosdepinstall--fromsrc-i--rosdistrojazzy + +Language: unknown +colconbuild--symlink-install + +Language: unknown +exportRMW_IMPLEMENTATION=rmw_gurumdds_cpp + +Language: unknown +ros2rundemo_nodes_cpptalker + +Language: unknown +ros2rundemo_nodes_cpplistener diff --git a/exported_docs/ros2/How_To_Guides.txt b/exported_docs/ros2/How_To_Guides.txt new file mode 100644 index 0000000..af25c75 --- /dev/null +++ b/exported_docs/ros2/How_To_Guides.txt @@ -0,0 +1,5 @@ +Title: How To Guides +URL: https://docs.ros.org/en/jazzy/How-To-Guides.html +Section: How-To-Guides +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/ros2/How_to_use_ros2_tracing_to_trace_and_analyze_an_application\357\203\201.txt" "b/exported_docs/ros2/How_to_use_ros2_tracing_to_trace_and_analyze_an_application\357\203\201.txt" new file mode 100644 index 0000000..cc6c000 --- /dev/null +++ "b/exported_docs/ros2/How_to_use_ros2_tracing_to_trace_and_analyze_an_application\357\203\201.txt" @@ -0,0 +1,80 @@ +Title: How to use ros2_tracing to trace and analyze an application +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/ROS2-Tracing-Trace-and-Analyze.html +Section: Installation +-------------------------------------------------------------------------------- + +How to use ros2_tracing to trace and analyze an applicationThis tutorial shows how to useros2_tracingto trace and analyze a ROS 2 application. +For this tutorial, the application will beperformance_test.OverviewThis tutorial covers:running and tracing aperformance_testrunanalyzing the trace data usingtracetools_analysisto plot the callback durationsPrerequisitesThis tutorial is aimed at real-time Linux systems. +See thereal-time system setup tutorial. +However, the tutorial will work if you are using a non-real-time Linux system.Installing and buildingInstall ROS 2 on Linux by following theinstallation instructions.NoteThis tutorial should generally work with all supported Linux distributions. +However, you might need to adapt some commands.Installbabeltraceandros2trace.sudoapt-getupdate +sudoapt-getinstall-ybabeltraceros-jazzy-ros2traceros-jazzy-tracetools-analysisSource the ROS 2 installation and verify that tracing is enabled:source/opt/ros/jazzy/setup.bash +ros2runtracetoolsstatusYou should seeTracingenabledin the output.Then create a workspace, and cloneperformance_testandtracetools_analysis.cd~/ +mkdir-ptracing_ws/srccdtracing_ws/src/ +gitclonehttps://gitlab.com/ApexAI/performance_test.git +gitclonehttps://github.com/ros-tracing/tracetools_analysis.git-bjazzycd..Install dependencies with rosdep.rosdepupdate +rosdepinstall--from-pathssrc--ignore-src-yThen build and configureperformance_testfor ROS 2. +See itsdocumentation.colconbuild--packages-selectperformance_test--cmake-args-DPERFORMANCE_TEST_RCLCPP_ENABLED=ONNext, we will run aperformance_testexperiment and trace it.TracingStep 1: TraceIn one terminal, source the workspace and set up tracing. +When running the command, a list of ROS 2 userspace events will be printed. +It will also print the path to the directory that will contain the resulting trace (under~/.ros/tracing).# terminal 1cd~/tracing_wssourceinstall/setup.bash +ros2trace--session-nameperf-test--listPress enter to start tracing.Step 2: Run ApplicationIn a second terminal, source the workspace.# terminal 2cd~/tracing_wssourceinstall/setup.bashThen run theperformance_testexperiment (or your own application). +We simply create an experiment with a node publishing ~1 MB messages to another node as fast as possible for 60 seconds using the second highest real-time priority so that we don’t interfere with critical kernel threads. +We need to runperformance_testasrootto be able to use real-time priorities.# terminal 2sudo./install/performance_test/lib/performance_test/perf_test-crclcpp-single-threaded-executor-p1-s1-r0-mArray1m--reliabilityRELIABLE--max-runtime60--use-rt-prio98If that last command doesn’t work for you (with an error like: “error while loading shared libraries”), run the slightly-different command below. +This is because, for security reasons, we need to manually pass*PATHenvironment variables for some shared libraries to be found (seethis explanation).# terminal 2sudoenvPATH="$PATH"LD_LIBRARY_PATH="$LD_LIBRARY_PATH"./install/performance_test/lib/performance_test/perf_test-crclcpp-single-threaded-executor-p1-s1-r0-mArray1m--reliabilityRELIABLE--max-runtime60--use-rt-prio98NoteIf you’re not using a real-time kernel, simply run:# terminal 2./install/performance_test/lib/performance_test/perf_test-crclcpp-single-threaded-executor-p1-s1-r0-mArray1m--reliabilityRELIABLE--max-runtime60Step 3: Validate TraceOnce the experiment is done, in the first terminal, press enter again to stop tracing. +Usebabeltraceto quickly look at the resulting trace.babeltrace~/.ros/tracing/perf-test|lessThe output of the above command is a human-readable version of the raw Common Trace Format (CTF) data, which is a list of trace events. +Each event has a timestamp, an event type, some information on the process that generated the event, and the values of the fields of the given event type.Use the arrow keys to scroll, or pressqto exit.Next, we will analyze the trace.Analysistracetools_analysisprovides a Python API to easily analyze traces. +We can use it in aJupyter notebookwithbokehto plot the data. +Thetracetools_analysisrepository contains afew sample notebooks, includingone notebook to analyze subscription callback durations.For this tutorial, we will plot the durations of the subscription callback in the subscriber node.Install Jupyter notebook and bokeh, and then open the sample notebook.pip3installbokeh +jupyternotebook~/tracing_ws/src/tracetools_analysis/tracetools_analysis/analysis/callback_duration.ipynbThis will open the notebook in the browser.Replace the value for thepathvariable in the second cell to the path to the trace directory:path='~/.ros/tracing/perf-test'Run the notebook by clicking theRunbutton for each cell. +Running the cell that does the trace processing might take a few minutes on the first run, but subsequent runs will be much quicker.You should get a plot that looks similar to this:We can see that most of the callbacks take less than 0.01 ms, but there are some outliers taking over 0.02 or 0.03 ms.ConclusionThis tutorial showed how to install tracing-related tools. +Then it showed how to trace aperformance_testexperiment usingros2_tracingand plot the callback durations usingtracetools_analysis.For more trace analyses, take a look at theother sample notebooksand thetracetools_analysis API documentation. +Theros2_tracing design documentalso contains a lot of information. + +Code Examples: + +Language: unknown +sudoapt-getupdate +sudoapt-getinstall-ybabeltraceros-jazzy-ros2traceros-jazzy-tracetools-analysis + +Language: unknown +source/opt/ros/jazzy/setup.bash +ros2runtracetoolsstatus + +Language: unknown +cd~/ +mkdir-ptracing_ws/srccdtracing_ws/src/ +gitclonehttps://gitlab.com/ApexAI/performance_test.git +gitclonehttps://github.com/ros-tracing/tracetools_analysis.git-bjazzycd.. + +Language: unknown +rosdepupdate +rosdepinstall--from-pathssrc--ignore-src-y + +Language: unknown +colconbuild--packages-selectperformance_test--cmake-args-DPERFORMANCE_TEST_RCLCPP_ENABLED=ON + +Language: unknown +# terminal 1cd~/tracing_wssourceinstall/setup.bash +ros2trace--session-nameperf-test--list + +Language: unknown +# terminal 2cd~/tracing_wssourceinstall/setup.bash + +Language: unknown +# terminal 2sudo./install/performance_test/lib/performance_test/perf_test-crclcpp-single-threaded-executor-p1-s1-r0-mArray1m--reliabilityRELIABLE--max-runtime60--use-rt-prio98 + +Language: unknown +# terminal 2sudoenvPATH="$PATH"LD_LIBRARY_PATH="$LD_LIBRARY_PATH"./install/performance_test/lib/performance_test/perf_test-crclcpp-single-threaded-executor-p1-s1-r0-mArray1m--reliabilityRELIABLE--max-runtime60--use-rt-prio98 + +Language: unknown +# terminal 2./install/performance_test/lib/performance_test/perf_test-crclcpp-single-threaded-executor-p1-s1-r0-mArray1m--reliabilityRELIABLE--max-runtime60 + +Language: unknown +babeltrace~/.ros/tracing/perf-test|less + +Language: unknown +pip3installbokeh +jupyternotebook~/tracing_ws/src/tracetools_analysis/tracetools_analysis/analysis/callback_duration.ipynb + +Language: unknown +path='~/.ros/tracing/perf-test' diff --git "a/exported_docs/ros2/Humble_Hawksbill_(humble)\357\203\201.txt" "b/exported_docs/ros2/Humble_Hawksbill_(humble)\357\203\201.txt" new file mode 100644 index 0000000..ef89aa5 --- /dev/null +++ "b/exported_docs/ros2/Humble_Hawksbill_(humble)\357\203\201.txt" @@ -0,0 +1,225 @@ +Title: Humble Hawksbill (humble) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Humble-Hawksbill.html +Section: Installation +-------------------------------------------------------------------------------- + +Humble Hawksbill (humble)Table of ContentsSupported PlatformsInstallationChanges in Patch Release 1 (2022-11-23)ros2topicNew features in this ROS 2 releaseament_cmake_gen_version_hlaunchlaunch_rosSROS2 Security enclaves support Certificate Revocation ListsContent Filtered Topicsros2clirviz2Changes since the Galactic releaseC++ headers are installed in a subdirectorycommon_interfacesrmwrmw_connextddsrclrclcpprclcpp_lifecyclerclpyros1_bridgeros2clirobot_state_publisherrosidl_cmakerviz2geometry2rosbag2Known IssuesRelease TimelineHumble Hawksbillis the eighth release of ROS 2. +What follows is highlights of the important changes and features in Humble Hawksbill since the last release. +For a list of all of the changes since Galactic, see thelong form changelog.Supported PlatformsHumble Hawksbill is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 22.04 (Jammy):amd64andarm64Windows 10 (Visual Studio 2019):amd64Tier 2 platforms:RHEL 8:amd64Tier 3 platforms:Ubuntu 20.04 (Focal):amd64macOS:amd64Debian Bullseye:amd64For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Humble HawksbillChanges in Patch Release 1 (2022-11-23)ros2topicnowas keyword forbuiltin_interfaces.msg.Timeandautoforstd_msgs.msg.Headerros2topicpubnow allows to set abuiltin_interfaces.msg.Timemessage to the current time via thenowkeyword. +Similarly, astd_msg.msg.Headermessage will be automatically generated when passed the keywordauto. +This behavior matches that of ROS 1’srostopic(http://wiki.ros.org/ROS/YAMLCommandLine#Headers.2Ftimestamps)Related PR:ros2/ros2cli#751New features in this ROS 2 releaseament_cmake_gen_version_hGenerating a C/C++ header with version infoA new CMake function to generate a header with the package version info was added to theament_cmake_gen_version_hinament/ament_cmake#377. +Here’s the simplest use case:project(my_project)add_library(my_lib...)ament_generate_version_header(my_lib)It will generate a header with version info from thepackage.xmland make it available to targets that link against themy_liblibrary.How to include the header:#includeWhere the header is installed to:set(VERSION_HEADER${CMAKE_INSTALL_PREFIX}/include/my_project/my_project/version.h)launchScoping environment variables in group actionsSimilar to launch configurations, now by default, the state of environment variables are scoped to group actions.For example, in the following launch files the executed processe will echo the value1(before Humble it would echo2):XMLPythonimportlaunchimportlaunch.actionsdefgenerate_launch_description():returnlaunch.LaunchDescription([launch.actions.SetEnvironmentVariable(name='FOO',value='1'),launch.actions.GroupAction([launch.actions.SetEnvironmentVariable(name='FOO',value='2'),]),launch.actions.ExecuteProcess(cmd=['echo','$FOO'],output='screen',shell=True),])If you would like disable scoping for launch configurations and and environment variables you can set thescopedargument (or attribute) to false.Related PR:ros2/launch#601launch_pytestWe’ve added a new package,launch_pytest, that acts as an alternative tolaunch_testing.launch_pytestis a simple pytest plugin that provides pytest fixtures to manage the lifetime of a launch service.Check out thepackage README for details and examples.Related PR:ros2/launch#528Allow matching target actions with a callableEvent handlers that take a target action object to match can now also take a callable instead to do the matching.Related PR:ros2/launch#540Access to math module when evaluating Python expressionsInsidePythonExpressionsubstitutions (eval) we can now use symbols from Python’s math module. +For example,Related PR:ros2/launch#557Boolean substitutionsNew substitutionsNotSubstitution,AndSubstitution, andOrSubstitutionprovide a convenient way to perform logical operations, for exampleRelated PR:ros2/launch#598New actionsAppendEnvironmentVariableappends a value to an existing environment variable.Related PR:ros2/launch#543ResetLaunchConfigurationsresets any configuration applied to the launch configuration.Related PR:ros2/launch#515launch_rosPassing ROS arguments to node actionsIt is now possible to provideROS-specific node argumentsdirectly, without needing to useargswith a leading--ros-argsflag:XMLYAMLlaunch:-node:pkg:demo_nodes_cppexec:talkerros_args:'--log-leveldebug'The corresponding parameter for theNodeaction in Python launch files isros_arguments:fromlaunchimportLaunchDescriptionimportlaunch_ros.actionsdefgenerate_launch_description():returnLaunchDescription([launch_ros.actions.Node(package='demo_nodes_cpp',executable='talker',ros_arguments=['--log-level','debug'],),])Related PRs:ros2/launch_ros#249andros2/launch_ros#253.Frontend support for composable nodesWe can now start node containers and load components into them from frontend launch files, for example:XMLYAMLlaunch:-node_container:pkg:rclcpp_componentsexec:component_containername:my_containernamespace:''composable_node:-pkg:compositionplugin:composition::Talkername:talker-load_composable_node:target:my_containercomposable_node:-pkg:compositionplugin:composition::Listenername:listenerRelated PR:ros2/launch_ros#235Parameter substitutionThe newParameterSubstitutionlets you substitute the value of a parameter set previously in launch with theSetParameteraction. +For example,Related PR:ros2/launch_ros#297New actionsRosTimeracts like the launchTimerAction, but uses a ROS clock (so it can use simulation time, for example).Related PRs:ros2/launch_ros#244andros2/launch_ros#264SetParametersFromFilepasses a ROS parameters file to all nodes in a launch file (including node components).Related PRs:ros2/launch_ros#260andros2/launch_ros#281SROS2 Security enclaves support Certificate Revocation ListsCertificate Revocation Lists (CRLs) are a concept where particular certificates can be revoked before their expiration. +As of Humble, it is now possible to put a CRL in an SROS2 security enclave and have it be honored. +Seethe SROS2 tutorialsfor an example of how to use it.Content Filtered TopicsContent Filtered Topics supports a more sophisticated subscription that indicates the subscriber does not want to necessarily see all values of each instance published under the Topic. +Content Filtered Topics can be used to request content-based subscriptions when underlying RMW implementation supports this feature.RMW Content Filtered Topics supportrmw_fastrtpssupportedrmw_connextddssupportedrmw_cycloneddsnot supportedTo learn more, see thecontent_filteringexamples.Related design PR:ros2/design#282.ros2cliros2launchhas a--launch-prefixargumentThis allows passing a prefix to all executables in a launch file, which is useful in many debugging situations. +See the associatedpull request, as well as thetutorialfor more information.Relatedly, the--launch-prefix-filtercommand-line option was added to selectively add the prefix from--launch-prefixto executables. +See thepull requestfor more information.ros2topicechohas a--flow-styleargumentThis allows the user to forceflowstylefor the YAML representation of data on a topic. +Without this option, the output fromros2topicecho/tf_staticcould look something like:transforms:-header:stamp:sec:1651172841nanosec:433705575frame_id:single_rrbot_link3child_frame_id:single_rrbot_camera_linktransform:translation:x:0.05y:0.0z:0.9rotation:x:0.0y:0.0z:0.0w:1.0With this option, the output would look something like:transforms:[{header:{stamp:{sec:1651172841,nanosec:433705575},frame_id:single_rrbot_link3},child_frame_id:single_rrbot_camera_link,transform:{translation:{x:0.05,y:0.0,z:0.9},rotation:{x:0.0,y:0.0,z:0.0,w:1.0}}}]See thePyYAML documentationfor more information.ros2topicechocan filter data based on message contentsThis allows the user to only print out data on a topic that matches a certain Python expression. +For instance, using the following argument will only print out string messages that start with ‘foo’:ros2topicecho--filter'm.data.startswith("foo")` /chatterSee thepull requestfor more information.rviz2Apply textures to arbitrary triangle listsWe’ve addedthe ability to apply textures defined via URI to arbitrary triangle lists using UV Coordinates. +Now we can create a gradient pull from a texture map instead of the default grayscale. +This will enable complex coloring of markers. +To use this, you should use thevisualization_msgs/Marker.msgand fill thetexture_resource,texture,uv_coordinatesandmesh_filefields. +You can find more informationhere.Visualization of mass properties (including inertia)We also added the ability to visualize inertias. To do this, you select enable ‘Inertia’ in the ‘Mass Properties’ under the robot model:You can see an image of an inertia below.Visualize YUV images in RVizIt is now possible to directly visualize YUV images inside of RViz, rather than having to convert to RGB first. +Seeros2/rviz#701for details.Allow rendering of objects > 100 metersBy default, RViz only renders objects that are within 100 meters of a camera. +A new configuration property called “Far Plane Distance” in the rviz camera plugin allows that rendering distance to be configured.Seeros2/rviz#849for more information.Changes since the Galactic releaseC++ headers are installed in a subdirectoryIn ROS 2 releases prior to Humble, C++ headers for all packages were installed into a single include directory. +For instance, in Galactic, the directory structure looks like this (reduced for brevity):/opt/ros/galactic/include/ +├── rcl +│   ├── node.h +├── rclcpp +│   ├── node.hppThis structure can cause serious problems when trying to use overlays. +That is, it is very possible to get the wrong set of header files due to include directory order. +Seehttps://colcon.readthedocs.io/en/released/user/overriding-packages.htmlfor a detailed explanation of the problems.To help combat this, in Humble (and in all ROS 2 releases going forward), the directory structure has changed:/opt/ros/humble/include +├── rcl +│   └── rcl +│   ├── node.h +├── rclcpp +│   └── rclcpp +│   ├── node.hppNote that downstream packages that use these headers donothave to change; using#includeworks as it always did before. +However, when using IDEs that are looking for include directories, it may be necessary to add the individual include directories to the search path.Seehttps://github.com/ros2/ros2/issues/1150for more information, including the reasoning behind this change.common_interfacesSupport Textures and Embedded Meshes for Marker MessagesThese two additions will improve the ability to both visualize data in new ways with standard messages and, simultaneously, enable the ability to track this data in rosbag.Texturesbring the addition of three new fields to markers:# Texture resource is a special URI that can either reference a texture file in# a format acceptable to (resource retriever)[https://index.ros.org/p/resource_retriever/]# or an embedded texture via a string matching the format:# "embedded://texture_name"stringtexture_resource# An image to be loaded into the rendering engine as the texture for this marker.# This will be used iff texture_resource is set to embedded.sensor_msgs/CompressedImagetexture# Location of each vertex within the texture; in the range: [0.0-1.0]UVCoordinate[]uv_coordinatesRViz will fully support texture rendering through the embedded format.To those familiar withmesh_resource,resource_retrievershould be familiar. +This will allow the programmer to choose where they want to load data from, either a local file or a networked file. +In the interest of being able to record all data in a rosbag, the ability to embed the texture image is included.Mesheswere modified in a similar way to add the ability to embed a raw Mesh file for the purpose of recording and are modified in a similar way. The Meshfile message has two fields:# The filename is used for both debug purposes and to provide a file extension# for whatever parser is used.stringfilename# This stores the raw text of the mesh file.uint8[]dataThe embeddedMeshfilemessage is not yet supported in implementation.Related PRs:ros2/common_interfaces#153ros2/rviz#719AddedPRISMtype to SolidPrimitiveTheSolidPrimitivemessage had a newPRISMtype added, along with the appropriate metadata. +Seeros2/common_interfaces#167for more information.rmwstructtype name suffix changed from_tto_sTo avoid type name duplication errors betweenstructtype names and theirtypedef-ed aliases when generating code documentation, the suffix for allstructtype names has been changed from_tto_s. +Aliases with_tsuffixes remain in place. +Thus, this change is a breaking change only for code that uses fullstructtype specifiers i.e.structtype_name_t.Seeros2/rmw#313for more details.rmw_connextddsUse Connext 6 by defaultBy default, Humble Hawksbill uses Connext 6.0.1 as the DDS implementation forrmw_connextdds. +It is still possible to use Connext 5.3.1 withrmw_connextdds, but it must be rebuilt from source.rclstructtype name suffix changed from_tto_sTo avoid type name duplication errors betweenstructtype names and theirtypedef-ed aliases when generating code documentation, the suffix for allstructtype names has been changed from_tto_s. +Aliases with_tsuffixes remain in place. +Thus, this change is a breaking change only for code that uses fullstructtype specifiers i.e.structtype_name_t.Seeros2/rcl#932for more details.ROS_DISABLE_LOANED_MESSAGES environment variable addedThis environment variable can be used to disable loaned messages support, independently if the rmw supports them or not. +For more details, see the guideConfigure Zero Copy Loaned Messages.rclcppSupport Type Adaption for Publishers and SubscriptionsAfter defining a type adapter, custom data structures can be used directly by publishers and subscribers, which helps to avoid additional work for the programmer and potential sources of errors. +This is especially useful when working with complex data types, such as when converting OpenCV’scv::Matto ROS’ssensor_msgs/msg/Imagetype.Here is an example of a type adapter that convertsstd_msgs::msg::Stringtostd::string:template<>structrclcpp::TypeAdapter{usingis_specialized=std::true_type;usingcustom_type=std::string;usingros_message_type=std_msgs::msg::String;staticvoidconvert_to_ros_message(constcustom_type&source,ros_message_type&destination){destination.data=source;}staticvoidconvert_to_custom(constros_message_type&source,custom_type&destination){destination=source.data;}};And an example of how the type adapter can be used:usingMyAdaptedType=TypeAdapter;// Publish a std::stringautopub=node->create_publisher(...);std::stringcustom_msg="My std::string"pub->publish(custom_msg);// Pass a std::string to a subscription's callbackautosub=node->create_subscription("topic",10,[](conststd::string&msg){...});To learn more, see thepublisherandsubscriptionexamples, as well as a more complexdemo. +For more details, seeREP 2007.Client::asnyc_send_request(request)returns astd::futureinstead of astd::shared_futureThis change was implemented inrclcpp#1734. +This breaks API, asstd::future::get()methods extracts the value from the future. +That means, if that method is called for a second time it will throw an exception. +That doesn’t happen with astd::shared_future, as itsget()method returns aconst&. +Example:autofuture=client->async_send_request(req);...do_something_with_response(future.get());...do_something_else_with_response(future.get());// this will throw an exception now!!should be updated to:autofuture=client->async_send_request(req);...autoresponse=future.get();do_something_with_response(response);...do_something_else_with_response(response);If a shared future is needed, thestd::future::share()method can be used.wait_for_all_ackedmethod added toPublisherThis new method will block until all messages in the publisher queue are acked by the matching subscriptions or the specified timeout expires. +It is only useful for reliable publishers, as in the case of best effort QoS there’s no acking. +Examples:autopub=node->create_publisher(...);...pub->publish(my_msg);...pub->wait_for_all_acked();// or pub->wait_for_all_acked(timeout)For a more complete example, seehere.get_callback_groupsmethod removed fromNodeBaseandNodeclassesfor_each_callback_group()method has replacedget_callback_groups()by providing a thread-safe way to accesscallback_groups_vector.for_each_callback_group()accepts a function as an argument, iterates over the stored callback groups, and calls the passed function to ones that are valid.For more details, please refer to thispull request.add_to_wait_setmethod fromWaitableclass changes its return type frombooltovoidBefore, classes derived fromWaitableoverridingadd_to_wait_setwere returning false when failing to add elements to the wait set, so the caller had to check this return value and throw or handle the error. +This error handling should now be done directly onadd_to_wait_setmethod, throwing if necessary. +It is not required to return anything if no errors happened. +Thus, this is a breaking change for downstream uses ofWaitable.Seeros2/rclcpp#1612for more details.get_notify_guard_conditionmethod return type fromNodeBaseInterfaceclass changedNowrclcppuses theGuardConditionclass wrapper aroundrcl_guard_condition_t, soget_notify_guard_conditionreturns a reference to the node’srclcpp::GuardCondition. +Thus, this is a breaking change for downstream uses ofNodeBaseInterfaceandNodeBase.Seeros2/rclcpp#1612for more details.sleep_untilandsleep_formethods added toClockTwo new methods were added to allow sleeping on a particular clock inros2/rclcpp#1814andros2/rclcpp#1828.Clock::sleep_untilwill suspend the current thread until the clock reaches a particular time.Clock::sleep_forwill suspend the current thread until the clock advances a certain amount of time from when the method was called. +Both methods will wake early if theContextis shutdown.rclcpp_lifecycleActive and deactivate transitions of publishers will be triggered automaticallyBefore, users needed to overrideLifecylceNode::on_activate()andLifecylceNode::on_deactivate()and call the similarly named methods onLifecyclePublisherto make the transition actually happen. +Now,LifecylceNodeprovides a default interface of these methods that already do this. +See the implementation of thelifecycle_talkernodehere.rclpyManaged nodesLifecycle nodes support was added to rclpy. +A complete demo can be foundhere.wait_for_all_ackedmethod added toPublisherSimilar to the feature added to rclcpp.sleep_untilandsleep_formethods added toClockTwo new methods were added to allow sleeping on a particular clock inros2/rclpy#858andros2/rclpy#864.sleep_untilwill suspend the current thread until the clock reaches a particular time.sleep_forwill suspend the current thread until the clock advances a certain amount of time from when the method was called. +Both methods will wake early if theContextis shutdown.ros1_bridgeSince there is no official ROS 1 distribution on Ubuntu Jammy and forward,ros1_bridgeis now compatible with the Ubuntu-packaged versions of ROS 1. +More details about usingros1_bridgewith Jammy packages are available inthe how-to guides.ros2cliros2commands disable output buffering by defaultPrior to this release, running a command likeros2echo/chatter|grep"Hello"would not print any data until the output buffer was full. +Users could work around this by settingPYTHONUNBUFFERED=1, but that was not very user friendly.Instead, allros2commands now do line-buffering by default, so commands like the above work as soon as a newline is printed. +To disable this behavior and use default python buffering rules, use the option--use-python-default-buffering. +See theoriginal issueand thepull requestfor more information.ros2topicpubwill wait for one matching subscription when using--times/--once/-1When using--times/--once/-1flags,ros2topicpubwill wait for one matching subscription to be found before starting to publish. +This avoids the issue of the ros2cli node starting to publish before discovering a matching subscription, which results in some of the first messages being lost. +This is particularly unexpected when using a reliable qos profile.The number of matching subscriptions to wait before starting publishing can be configured with the-w/--wait-matching-subscriptionsflags, e.g.:ros2 topic pub -1 -w 3 /chatter std_msgs/msg/String "{data: 'foo'}"to wait for three matching subscriptions before starting to publish.-wcan also be used independently of--times/--once/-1but it only defaults to one when combined with them, otherwise the-wdefault is zero.Seehttps://github.com/ros2/ros2cli/pull/642for more details.ros2paramdumpdefault output changed--printoption for dump command wasdeprecated.It prints to stdout by default:ros2paramdump/my_node_name--output-diroption for dump command wasdeprecated.To dump parameters to a file, run:ros2paramdump/my_node_name>my_node_name.yamlros2paramsetnow accepts more YAML syntaxPreviously, attempting to set a string like “off” to a parameter that was of string type did not work. +That’s becauseros2paramsetinterprets the command-line arguments as YAML, and YAML considers “off” to be a boolean type. +As ofhttps://github.com/ros2/ros2cli/pull/684,ros2paramsetnow accepts the YAML escape sequence of “!!str off” to ensure that the value is considered a string.ros2pkgcreatecan automatically generate a LICENSE fileIf the--licenseflag is passed toros2pkgcreate, and the license is one of the known licenses,ros2pkgcreatewill now automatically generate a LICENSE file in the root of the package. +For a list of known licenses, runros2pkgcreate--license?. +See the associatedpull requestfor more information.robot_state_publisherAddedframe_prefixparameterA new parameterframe_prefixwas added inros/robot_state_publisher#159. +This parameter is a string which is prepended to all frame names published byrobot_state_publisher. +Similar totf_prefixin the originaltflibrary in ROS 1, this parameter can be used to publish the same robot description multiple times with different frame names.Removal of deprecateduse_tf_staticparameterThe deprecateduse_tf_staticparameter has been removed fromrobot_state_publisher. +This means that static transforms are unconditionally published to the/tf_statictopic, and that the static transforms are published in atransient_localQuality of Service. +This was the default behavior, and the behavior which thetf2_ros::TransformListenerclass expected before, so most code will not have to be changed. +Any code that was relying onrobot_state_publisherto periodically publish static transforms to/tfwill have to be updated to subscribe to/tf_staticas atransient_localsubscription instead.rosidl_cmakeDeprecation ofrosidl_target_interfaces()The CMake functionrosidl_target_interfaces()has been deprecated, and now issues a CMake warning when called. +Users wanting to use messages/services/actions in the same ROS package that generated them should instead callrosidl_get_typesupport_target()and thentarget_link_libraries()to make their targets depend on the returned typesupport target. +Seehttps://github.com/ros2/rosidl/pull/606for more details, andhttps://github.com/ros2/demos/pull/529for an example of using the new function.rviz2improved the efficiency of 3-bytes pixel formatschanged the way inertias are computed to use ignition math rather than Ogre’s math libraries.geometry2Deprecation of TF2Error::NO_ERROR, etcThetf2library uses an enumeration calledTF2Errorto return errors. +Unfortunately, one of the enumerators in there is calledNO_ERROR, which conflicts with a macro on Windows. +To remedy this, a new set of enumerators inTF2Errorwere created, each with aTF2prefix. +The previous enumerators are still available, but are now deprecated and will print a deprecation warning if used. +All code that uses theTF2Errorenumerator should be updated to use the newTF2prefixed errors. +Seehttps://github.com/ros2/geometry2/pull/349for more details.More intuitive command-line arguments for static_transform_publisherThestatic_transform_publisherprogram used to take arguments like:ros2runtf2_rosstatic_transform_publisher0000001foobar. +The first three numbers are the translation x, y, and z, the next 4 are the quaternion x, y, z, and w, and the last two arguments are the parent and child frame IDs. +While this worked, it had a couple of problems:The user had to specifyallof the arguments, even if only setting one numberReading the command-line to figure out what it was publishing was trickyTo fix both of these issues, the command-line handling has been changed to use flags instead, and all flags except for--frame-idand--child-frame-idare optional. +Thus, the above command-line can be simplified to:ros2runtf2_rosstatic_transform_publisher--frame-idfoo--child-frame-idbarTo change just the translation x, the command-line would be:ros2runtf2_rosstatic_transform_publisher--x1.5--frame-idfoo--child-frame-idbar.The old-style arguments are still allowed in this release, but are deprecated and will print a warning. +They will be removed in future releases. +Seehttps://github.com/ros2/geometry2/pull/392for more details.Transform listener spin thread no longer executes node callbackstf2_ros::TransformListenerno longer spins on the provided node object. +Instead, it creates a callback group to execute callbacks on the entities it creates internally. +This means if you have set the parameterspin_thread=truewhen creating a transform listener, you +can no longer depend on your own callbacks to be executed. +You must call aspinfunction on your node (e.g.rclcpp::spin), or add your node to your own executor.Related pull request:geometry2#442rosbag2New playback and recording controlsSeveral pull requests have been added to enhance the user’s control over playback of bags. +Pull request931adds the ability to specify a time stamp to begin playing from. +Due to pull request789it is now possible to delay the start of playback by a specified interval.Relatedly,rosbag2has gained new ways for users to control playback as it is happening. +Pull request847adds keyboard controls for pausing, resuming, and playing the next message during playback from a terminal. +It is also possible to start playback paused thanks to pull requests905and904, which makes it easy for the user to initiate playback and then step through messages, such as when debugging a pipeline. +Pull request836adds an interface for seeking within bags, allowing the user to move around within a bag during playback.Finally, a new snapshot mode has been added to recording in pull request851. +This mode, useful for incident recording, allows recording to begin filling up buffers, but not begin writing data to disc until a service is called.Burst-mode playbackWhile the playback of data from a bag in real-time is the most well-known use case for bag files, there are situations where you want the data in the bag as fast as possible. +With pull request977,rosbag2has gained the ability to “burst” data from the bag. +In burst mode, the data is played back as fast as possible. +This is useful in applications such as machine learning.Zero-Copy playbackBy default, if loaned message can be used, playback messages are published as loaned message. +This can help to reduce the number of data copies, so there is a greater benefit for sending big data. +Pull request981adds--disable-loan-messageoption for playback.Wait for an acknowledgmentThis new option will wait until all published messages are acknowledged by all subscribers or until the timeout elapses in millisecond before play is terminated. +Especially for the case of sending message with big size in a short time. +This option is valid only if the publisher’s QOS profile is RELIABLE. +Pull request951adds--wait-for-all-ackedoption for playback.Bag editingrosbag2is taking steps towards enabling the editing of bags, such as removing all messages for one topic or merging multiple bags into a single bag. +Pull request921adds bag rewriting and theros2bagconvertverb.Other changesPull request925makesrosbag2ignore “leaf topics” (topics without a publisher) when recording. +These topics will no longer be automatically added to the bag.Known IssuesWheninstalling ROS 2 on an Ubuntu 22.04 Jammy hostit is important to update your system before installing ROS 2 packages. +It isparticularlyimportant to make sure thatsystemdandudevare updated to the latest available version otherwise installingros-humble-desktop, which depends onlibudev1, could cause the removal of system critical packages. +Details can be found inros2/ros2#1272andLaunchpad #1974196When ROS 2 apt repositories are available, ROS 1 packages in Ubuntu are not installable. See theros1_bridge on Ubuntu Jammydocument for more information.Some major Linux distributions have started patching Python to install packages to/usr/local, which is breaking some parts ofament_packageand builds withcolcon. +In particular, using Ubuntu Jammy withsetuptoolsinstalled from pip will manifest this misbehavior, and is therefore not recommended. +There is currently aproposed solutionwhich requires further testing before widespread release.ROS 2 bags that are split by size or duration are not played correctly. +Only the last bag recorded is played. +It is recommended to avoid splitting bags by size or duration. +Details can be found inros2/rosbag2#966.Release TimelineMon. March 21, 2022 - Alpha + RMW freezePreliminary testing and stabilization of ROS Base[1]packages, and API and feature freeze for RMW provider packages.Mon. April 4, 2022 - FreezeAPI and feature freeze for ROS Base[1]packages in Rolling Ridley. +Only bug fix releases should be made after this point. +New packages can be released independently.Mon. April 18, 2022 - BranchBranch from Rolling Ridley.rosdistrois reopened for Rolling PRs for ROS Base[1]packages. +Humble development shifts fromros-rolling-*packages toros-humble-*packages.Mon. April 25, 2022 - BetaUpdated releases of ROS Desktop[2]packages available. +Call for general testing.Mon. May 16, 2022 - Release CandidateRelease Candidate packages are built. +Updated releases of ROS Desktop[2]packages available.Thu. May 19, 2022 - Distro FreezeFreeze rosdistro. +No PRs for Humble on therosdistrorepo will be merged (reopens after the release announcement).Mon. May 23, 2022 - General AvailabilityRelease announcement.rosdistrois reopened for Humble PRs.[1](1,2,3)Theros_basevariant is described inREP 2001 (ros-base).[2](1,2)Thedesktopvariant is described inREP 2001 (desktop-variants). + +Code Examples: + +Language: unknown +project(my_project)add_library(my_lib...)ament_generate_version_header(my_lib) + +Language: unknown +#include + +Language: unknown +set(VERSION_HEADER${CMAKE_INSTALL_PREFIX}/include/my_project/my_project/version.h) + +Language: unknown + + +Language: unknown +importlaunchimportlaunch.actionsdefgenerate_launch_description():returnlaunch.LaunchDescription([launch.actions.SetEnvironmentVariable(name='FOO',value='1'),launch.actions.GroupAction([launch.actions.SetEnvironmentVariable(name='FOO',value='2'),]),launch.actions.ExecuteProcess(cmd=['echo','$FOO'],output='screen',shell=True),]) + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown +launch:-node:pkg:demo_nodes_cppexec:talkerros_args:'--log-leveldebug' + +Language: unknown +fromlaunchimportLaunchDescriptionimportlaunch_ros.actionsdefgenerate_launch_description():returnLaunchDescription([launch_ros.actions.Node(package='demo_nodes_cpp',executable='talker',ros_arguments=['--log-level','debug'],),]) + +Language: unknown + + +Language: unknown +launch:-node_container:pkg:rclcpp_componentsexec:component_containername:my_containernamespace:''composable_node:-pkg:compositionplugin:composition::Talkername:talker-load_composable_node:target:my_containercomposable_node:-pkg:compositionplugin:composition::Listenername:listener + +Language: unknown + + +Language: unknown +transforms:-header:stamp:sec:1651172841nanosec:433705575frame_id:single_rrbot_link3child_frame_id:single_rrbot_camera_linktransform:translation:x:0.05y:0.0z:0.9rotation:x:0.0y:0.0z:0.0w:1.0 + +Language: unknown +transforms:[{header:{stamp:{sec:1651172841,nanosec:433705575},frame_id:single_rrbot_link3},child_frame_id:single_rrbot_camera_link,transform:{translation:{x:0.05,y:0.0,z:0.9},rotation:{x:0.0,y:0.0,z:0.0,w:1.0}}}] + +Language: unknown +ros2topicecho--filter'm.data.startswith("foo")` /chatter + +Language: unknown +/opt/ros/galactic/include/ +├── rcl +│   ├── node.h +├── rclcpp +│   ├── node.hpp + +Language: unknown +/opt/ros/humble/include +├── rcl +│   └── rcl +│   ├── node.h +├── rclcpp +│   └── rclcpp +│   ├── node.hpp + +Language: unknown +# Texture resource is a special URI that can either reference a texture file in# a format acceptable to (resource retriever)[https://index.ros.org/p/resource_retriever/]# or an embedded texture via a string matching the format:# "embedded://texture_name"stringtexture_resource# An image to be loaded into the rendering engine as the texture for this marker.# This will be used iff texture_resource is set to embedded.sensor_msgs/CompressedImagetexture# Location of each vertex within the texture; in the range: [0.0-1.0]UVCoordinate[]uv_coordinates + +Language: unknown +# The filename is used for both debug purposes and to provide a file extension# for whatever parser is used.stringfilename# This stores the raw text of the mesh file.uint8[]data + +Language: unknown +template<>structrclcpp::TypeAdapter{usingis_specialized=std::true_type;usingcustom_type=std::string;usingros_message_type=std_msgs::msg::String;staticvoidconvert_to_ros_message(constcustom_type&source,ros_message_type&destination){destination.data=source;}staticvoidconvert_to_custom(constros_message_type&source,custom_type&destination){destination=source.data;}}; + +Language: unknown +usingMyAdaptedType=TypeAdapter;// Publish a std::stringautopub=node->create_publisher(...);std::stringcustom_msg="My std::string"pub->publish(custom_msg);// Pass a std::string to a subscription's callbackautosub=node->create_subscription("topic",10,[](conststd::string&msg){...}); + +Language: unknown +autofuture=client->async_send_request(req);...do_something_with_response(future.get());...do_something_else_with_response(future.get());// this will throw an exception now!! + +Language: unknown +autofuture=client->async_send_request(req);...autoresponse=future.get();do_something_with_response(response);...do_something_else_with_response(response); + +Language: unknown +autopub=node->create_publisher(...);...pub->publish(my_msg);...pub->wait_for_all_acked();// or pub->wait_for_all_acked(timeout) + +Language: unknown +ros2echo/chatter|grep"Hello" + +Language: unknown +ros2 topic pub -1 -w 3 /chatter std_msgs/msg/String "{data: 'foo'}" + +Language: unknown +ros2paramdump/my_node_name + +Language: unknown +ros2paramdump/my_node_name>my_node_name.yaml diff --git "a/exported_docs/ros2/Humble_Hawksbill_changelog\357\203\201.txt" "b/exported_docs/ros2/Humble_Hawksbill_changelog\357\203\201.txt" new file mode 100644 index 0000000..bc8e2b1 --- /dev/null +++ "b/exported_docs/ros2/Humble_Hawksbill_changelog\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Humble Hawksbill changelog +URL: https://docs.ros.org/en/jazzy/Releases/Humble-Hawksbill-Complete-Changelog.html +Section: Installation +-------------------------------------------------------------------------------- + +Humble Hawksbill changelogThis page is a list of the complete changes in all ROS 2 core packages since the previous release.Table of Contentsaction_msgsaction_tutorials_cppaction_tutorials_interfacesaction_tutorials_pyactionlib_msgsament_clang_formatament_clang_tidyament_cmakeament_cmake_autoament_cmake_clang_formatament_cmake_clang_tidyament_cmake_copyrightament_cmake_coreament_cmake_cppcheckament_cmake_cpplintament_cmake_export_definitionsament_cmake_export_dependenciesament_cmake_export_include_directoriesament_cmake_export_interfacesament_cmake_export_librariesament_cmake_export_link_flagsament_cmake_export_targetsament_cmake_flake8ament_cmake_gen_version_hament_cmake_gmockament_cmake_google_benchmarkament_cmake_gtestament_cmake_include_directoriesament_cmake_librariesament_cmake_lint_cmakeament_cmake_mypyament_cmake_noseament_cmake_pclintament_cmake_pep257ament_cmake_pycodestyleament_cmake_pyflakesament_cmake_pytestament_cmake_pythonament_cmake_rosament_cmake_target_dependenciesament_cmake_testament_cmake_uncrustifyament_cmake_versionament_cmake_xmllintament_copyrightament_cppcheckament_cpplintament_flake8ament_index_cppament_index_pythonament_lintament_lint_autoament_lint_cmakeament_lint_commonament_mypyament_packageament_pclintament_pep257ament_pycodestyleament_pyflakesament_uncrustifyament_xmllintbuiltin_interfacescamera_calibration_parserscamera_info_managerclass_loadercommon_interfacescompositioncomposition_interfacesdemo_nodes_cppdemo_nodes_cpp_nativedemo_nodes_pydiagnostic_msgsdomain_coordinatordummy_map_serverdummy_robot_bringupdummy_sensorsexample_interfacesexamples_rclcpp_async_clientexamples_rclcpp_cbg_executorexamples_rclcpp_minimal_action_clientexamples_rclcpp_minimal_action_serverexamples_rclcpp_minimal_clientexamples_rclcpp_minimal_compositionexamples_rclcpp_minimal_publisherexamples_rclcpp_minimal_serviceexamples_rclcpp_minimal_subscriberexamples_rclcpp_minimal_timerexamples_rclcpp_multithreaded_executorexamples_rclcpp_wait_setexamples_rclpy_executorsexamples_rclpy_guard_conditionsexamples_rclpy_minimal_action_clientexamples_rclpy_minimal_action_serverexamples_rclpy_minimal_clientexamples_rclpy_minimal_publisherexamples_rclpy_minimal_serviceexamples_rclpy_minimal_subscriberexamples_rclpy_pointcloud_publisherexamples_tf2_pyfastrtps_cmake_modulegeometry_msgsgoogle_benchmark_vendorimage_toolsimage_transportinteractive_markersintra_process_demokdl_parserlaser_geometrylaunchlaunch_pytestlaunch_roslaunch_testinglaunch_testing_ament_cmakelaunch_testing_exampleslaunch_testing_roslaunch_xmllaunch_yamllibcurl_vendorlibstatistics_collectorlibyaml_vendorlifecyclelifecycle_msgslifecycle_pylogging_demomessage_filtersmimick_vendornav_msgspendulum_controlpendulum_msgspluginlibpybind11_vendorpython_cmake_moduleqt_gui_cppquality_of_service_demo_cppquality_of_service_demo_pyrclrcl_actionrcl_interfacesrcl_lifecyclercl_logging_interfacercl_logging_nooprcl_logging_spdlogrcl_yaml_param_parserrclcpprclcpp_actionrclcpp_componentsrclcpp_lifecyclerclpyrcpputilsrcutilsresource_retrieverrmwrmw_connextddsrmw_connextdds_commonrmw_connextddsmicrormw_cyclonedds_cpprmw_dds_commonrmw_fastrtps_cpprmw_fastrtps_dynamic_cpprmw_fastrtps_shared_cpprmw_implementationrmw_implementation_cmakerobot_state_publisherros2actionros2bagros2cliros2cli_test_interfacesros2componentros2doctorros2interfaceros2launchros2lifecycleros2lifecycle_test_fixturesros2multicastros2noderos2paramros2pkgros2runros2serviceros2testros2topicros2tracerosbag2rosbag2_compressionrosbag2_compression_zstdrosbag2_cpprosbag2_interfacesrosbag2_performance_benchmarkingrosbag2_pyrosbag2_storagerosbag2_storage_default_pluginsrosbag2_test_commonrosbag2_testsrosbag2_transportrosgraph_msgsrosidl_adapterrosidl_clirosidl_cmakerosidl_default_generatorsrosidl_default_runtimerosidl_generator_crosidl_generator_cpprosidl_generator_dds_idlrosidl_generator_pyrosidl_parserrosidl_runtime_crosidl_runtime_cpprosidl_runtime_pyrosidl_typesupport_crosidl_typesupport_cpprosidl_typesupport_fastrtps_crosidl_typesupport_fastrtps_cpprosidl_typesupport_interfacerosidl_typesupport_introspection_crosidl_typesupport_introspection_cpprosidl_typesupport_introspection_testsrpyutilsrqt_guirqt_gui_cpprqt_gui_pyrqt_py_commonrti_connext_dds_cmake_modulerttestrviz2rviz_assimp_vendorrviz_commonrviz_default_pluginsrviz_ogre_vendorrviz_renderingrviz_rendering_testsrviz_visual_testing_frameworksensor_msgssensor_msgs_pyshape_msgsshared_queues_vendorsqlite3_vendorsros2statistics_msgsstd_msgsstd_srvsstereo_msgstest_clitest_cli_remappingtest_communicationtest_interface_filestest_launch_rostest_launch_testingtest_msgstest_quality_of_servicetest_rclcpptest_rmw_implementationtest_securitytest_tf2test_tracetoolstest_tracetools_launchtf2tf2_bullettf2_eigentf2_eigen_kdltf2_geometry_msgstf2_kdltf2_msgstf2_pytf2_rostf2_ros_pytf2_sensor_msgstf2_toolstlsftlsf_cpptopic_monitortopic_statistics_demotracetoolstracetools_launchtracetools_testtracetools_tracetrajectory_msgsturtlesimurdfurdf_parser_pluginvisualization_msgsyaml_cpp_vendorzstd_vendoraction_msgsUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashaction_tutorials_cppUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow Nashaction_tutorials_interfacesUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow Nashaction_tutorials_pyUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow Nashactionlib_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Greyament_clang_formatUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_clang_tidyUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)remove google style from clang-tidy default settings, removing need for default config file (#337)Improvements to ament_lint_clang_tidy. (#316)Contributors: Audrow Nash, Steven! Ragnarök, William Woodallament_cmakeUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Add ament_cmake_gen_version_h package (#198)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretz, serge-nikulinament_cmake_autoUpdate forthcoming version in changelogFix typo in ament_auto_find_test_dependencies (#363)Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Add ament_auto_add_gtest (#344)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Daisuke Nishimatsu, Joshua Whitley, Shane Loretzament_cmake_clang_formatUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_cmake_clang_tidyUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Improvements to ament_lint_clang_tidy. (#316)Contributors: Audrow Nash, Steven! Ragnarökament_cmake_copyrightIncrease the ament_cmake_copyright default timeout. (#355)Update forthcoming version in changelogs[ament_cmake_copyright] Add file exclusion support (#328) * [ament_cmake_copyright] Add file exclusion support In theament_copyrightCMake function, the optional list argumentEXCLUDEcan now be used as an exclusion specifier. * [ament_cmake_copyright] Fix function header typo Remove reference tocppcheckin theEXCLUDEarg description.Update maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancetteament_cmake_coreUpdate forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Support commands with executable targets (#352)doc/resource_index: Indent list subitems correctly (#342)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Michal Sojka, Scott K Logan, Shane Loretzament_cmake_cppcheckUpdate forthcoming version in changelogs[ament_cmake_cppcheck] Fix file exclusion behavior (#329) TheEXCLUDEargument of theament_cppcheckCMake function is a list, i.e. a multi-value keyword. As such, it needs to be placed out of the one-value keywords from thecmake_parse_argumentsfunction call.Update maintainers to Michael Jeronimo and Michel Hidalgo (#340)Add cppcheck libraries option (#323) * adding ament_cppcheck libraries option * pass libraries option via CMake Co-authored-by: William Wedler Contributors: Abrar Rahman Protyasha, Audrow Nash, Willament_cmake_cpplintUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_cmake_export_definitionsUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_export_dependenciesUpdate forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Scott K Logan, Shane Loretzament_cmake_export_include_directoriesUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_export_interfacesUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_export_librariesUpdate forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Add note regarding interface libraries (#339)Update maintainers (#336)Contributors: Audrow Nash, Bjar Ne, Chris Lalancette, Scott K Logan, Shane Loretzament_cmake_export_link_flagsUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_export_targetsUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_flake8Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Add custom config file support for flake8 (#331)Contributors: Audrow Nash, Kenji Miyakeament_cmake_gen_version_hAdd ament_generate_version_header and deprecate ament_cmake_gen_version_h (#377)Update forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Add ament_cmake_gen_version_h package (#198)Contributors: Audrow Nash, Shane Loretz, serge-nikulinament_cmake_gmockUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_google_benchmarkUpdate forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Scott K Logan, Shane Loretzament_cmake_gtestUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_include_directoriesUpdate forthcoming version in changelogMake ament_include_directories_order a function to allow paths with backslashes on windows. (#371) * Repalce backslashes with forward slashes on Windows * Typo * Replace slashes in ARGN * Don’t quote * Check ARGN has values before trying to string(REPLACE them * Make ament_include_directories_order a functionUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_librariesUpdate forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Scott K Logan, Shane Loretzament_cmake_lint_cmakeUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_cmake_mypyImprove documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1Nament_cmake_noseUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Support commands with executable targets (#352)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_pclintImprove documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1Nament_cmake_pep257Improve documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1Nament_cmake_pycodestyleImprove documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1Nament_cmake_pyflakesUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_cmake_pytestUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Fix misleading comment (#361)Use FindPython3 instead of FindPythonInterp (#355)Support commands with executable targets (#352)Mention other platforms in ‘pytest/pytest-cov not found’ warning (#337)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Christophe Bedard, Shane Loretzament_cmake_pythonUse sysconfig directly to determine python lib dir (#378)Update forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Make ament_cmake_python symlink for symlink installs only (#357)Use FindPython3 instead of FindPythonInterp (#355)Make ament_python_install_package() match setuptools’ egg names. (#338)Drop ament_cmake_python outdated tests. (#340)Update maintainers (#336)Make ament_python_install_package() install console_scripts (#328)Contributors: Audrow Nash, Chris Lalancette, Michel Hidalgo, Scott K Logan, Shane Loretzament_cmake_rosRefactor domain_coordinator API to use a context manager (#12)Contributors: Timo Röhlingament_cmake_target_dependenciesUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Fix bug packages with multiple configurations (#318)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_testUpdate forthcoming version in changelogResolve various ament_lint linter violations (#360) We can’t add ament_lint linters in ament_cmake in the traditional way without creating a circular dependency between the repositories. Even though we can’t automatically enforce linting, it’s still a good idea to try to keep conformance where possible.Update maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Scott K Logan, Shane Loretzament_cmake_uncrustifyUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)[ament_cmake_uncrustify] Add file exclude support (#330) In theament_uncrustifyCMake function, the optional list argumentEXCLUDEcan now be used as an exclusion specifier.Contributors: Abrar Rahman Protyasha, Audrow Nashament_cmake_versionUpdate forthcoming version in changelogUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#362)Use FindPython3 instead of FindPythonInterp (#355)Update maintainers (#336)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzament_cmake_xmllintUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_copyrightFix importlib_metadata warning on Python 3.10. (#365)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)[ament_copyright] Fix file exclusion behavior (#327) * [ament_copyright] Fix file exclusion behavior This commit fixes the faulty file exclusion behavior reported inhttps://github.com/ament/ament_lint/issues/326. Specifically, the exclusion list is matched against traversed files in thecrawlermodule. Changes inspired byhttps://github.com/ament/ament_lint/pull/299/. * Update excluded file path in copyright tests Since file names are not indiscriminately matched throughout the search tree anymore, the excluded files listed in the copyright tests need to be updated relative to the root of the package. * Add test cases to check exclusion behavior Specifically, these tests check for: - Incorrect exclusion of single filenames. - Correct exclusion of relatively/absolutely addressed filenames. - Correct exclusion of wildcarded paths. * Add unit tests for crawler module These unit tests make sure both search and exclusion behaviors are correctly demonstrated by theament_copyright.crawlermodule.Add SPDX identifiers to the licenses. (#315)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancetteament_cppcheckDisable cppcheck 2.x. (#345)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Add cppcheck libraries option (#323) * adding ament_cppcheck libraries option * pass libraries option via CMake Co-authored-by: William Wedler Contributors: Audrow Nash, Chris Lalancette, Willament_cpplintignore NOLINT comments with categories that come from clang-tidy (#339)Update forthcoming version in changelogsReapply patches Reapply parts of 232428752251de61e84ef013bcd643e35eb9038d that are still relevant.Update cpplint version Point to the forkhttps://github.com/cpplint/cpplintContains updates for modern C++ standards (e.g. C++14 and C++17).Update maintainers to Michael Jeronimo and Michel Hidalgo (#340)[ament_copyright] Fix file exclusion behavior (#327) * [ament_copyright] Fix file exclusion behavior This commit fixes the faulty file exclusion behavior reported inhttps://github.com/ament/ament_lint/issues/326. Specifically, the exclusion list is matched against traversed files in thecrawlermodule. Changes inspired byhttps://github.com/ament/ament_lint/pull/299/. * Update excluded file path in copyright tests Since file names are not indiscriminately matched throughout the search tree anymore, the excluded files listed in the copyright tests need to be updated relative to the root of the package. * Add test cases to check exclusion behavior Specifically, these tests check for: - Incorrect exclusion of single filenames. - Correct exclusion of relatively/absolutely addressed filenames. - Correct exclusion of wildcarded paths. * Add unit tests for crawler module These unit tests make sure both search and exclusion behaviors are correctly demonstrated by theament_copyright.crawlermodule.Contributors: Abrar Rahman Protyasha, Audrow Nash, Dirk Thomas, Jacob Perron, William Woodallament_flake8Remove use of distutils.version.LooseVersion. (#346)Update forthcoming version in changelogsIgnore .*/_* dirs in ament_flake8 (#335) Other ament_* linters specifically ignore directories starting with a dot or underscore when crawling for files to lint. They also do so implicitly, so this change mimics that same pattern so that the behavior is consistent.Update maintainers to Michael Jeronimo and Michel Hidalgo (#340)Ignore flake8-blind-except B902 (#292)Contributors: Audrow Nash, Chris Lalancette, Scott K Loganament_index_cppInstall includes to include/ (#83)Remove ament_export_include_directories and ament_export_libraries (#81)Contributors: Shane Loretzament_index_pythonPrint warning when get_package_share_directory() does not exist (Fix#74) (#77)Fail lookups on invalid resource names (#69)Add get_package_share_path method (#73)Contributors: David V. Lu, rob-clarkeament_lintUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_lint_autoUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_lint_cmakeUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)[ament_copyright] Fix file exclusion behavior (#327) * [ament_copyright] Fix file exclusion behavior This commit fixes the faulty file exclusion behavior reported inhttps://github.com/ament/ament_lint/issues/326. Specifically, the exclusion list is matched against traversed files in thecrawlermodule. Changes inspired byhttps://github.com/ament/ament_lint/pull/299/. * Update excluded file path in copyright tests Since file names are not indiscriminately matched throughout the search tree anymore, the excluded files listed in the copyright tests need to be updated relative to the root of the package. * Add test cases to check exclusion behavior Specifically, these tests check for: - Incorrect exclusion of single filenames. - Correct exclusion of relatively/absolutely addressed filenames. - Correct exclusion of wildcarded paths. * Add unit tests for crawler module These unit tests make sure both search and exclusion behaviors are correctly demonstrated by theament_copyright.crawlermodule.Contributors: Abrar Rahman Protyasha, Audrow Nashament_lint_commonUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Fix typo in ament_lint_common/package.xml (#336)Contributors: Audrow Nash, Kenji Miyakeament_mypyImprove documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1Nament_packageSet forthcoming for previous versionAdd support for appending to environment variables (#130) This works largely the same as ‘prepend-non-duplicate’, but instead puts the candidate value at the end of the target variable.Update maintainers to Audrow Nash (#135)Make python executable variable ament_package specific (#134)Contributors: Audrow Nash, Scott K Logan, Shane Loretzament_pclintImprove documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)[ament_copyright] Fix file exclusion behavior (#327) * [ament_copyright] Fix file exclusion behavior This commit fixes the faulty file exclusion behavior reported inhttps://github.com/ament/ament_lint/issues/326. Specifically, the exclusion list is matched against traversed files in thecrawlermodule. Changes inspired byhttps://github.com/ament/ament_lint/pull/299/. * Update excluded file path in copyright tests Since file names are not indiscriminately matched throughout the search tree anymore, the excluded files listed in the copyright tests need to be updated relative to the root of the package. * Add test cases to check exclusion behavior Specifically, these tests check for: - Incorrect exclusion of single filenames. - Correct exclusion of relatively/absolutely addressed filenames. - Correct exclusion of wildcarded paths. * Add unit tests for crawler module These unit tests make sure both search and exclusion behaviors are correctly demonstrated by theament_copyright.crawlermodule.Contributors: Abrar Rahman Protyasha, Audrow Nash, Bi0T1Nament_pep257Improve documentation by clarifying the purpose of different tools (#357)Remove use of distutils.version.LooseVersion. (#346)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1N, Chris Lalancetteament_pycodestyleImprove documentation by clarifying the purpose of different tools (#357)Update forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nash, Bi0T1Nament_pyflakesUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashament_uncrustifyUpdate forthcoming version in changelogs[ament_uncrustify] Fix file exclusion behavior (#334) * [ament_uncrustify] Fix file exclusion behavior This PR fixes the file exclusion behavior reported in#326. Specifically, the exclusion list is matched against files/directories as the search path is traversed. Tries to maintain consistency with#327. * [ament_uncrustify] Add file exclusion tests * [ament_uncrustify] Remove erroneous pytest markerUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)[ament_uncrustify] Add ament_lint tests (#338) * Addament_linttests onament_uncrustify* Address linter warnings inament_uncrustifyContributors: Abrar Rahman Protyasha, Audrow Nashament_xmllintUpdate forthcoming version in changelogsUpdate maintainers to Michael Jeronimo and Michel Hidalgo (#340)Contributors: Audrow Nashbuiltin_interfacesUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashcamera_calibration_parsersTests depend on rcpputils (#236)Remove YAML_CPP_DLL define (#231)Export a modern CMake target instead of variables and install includes to include/${PROJECT_NAME} (#218)Update maintainers (#173)Contributors: Akash, Alejandro Hernández Cordero, Shane Loretzcamera_info_managerExport a modern CMake target instead of variables and install includes to include/${PROJECT_NAME} (#218)Update maintainers (#173)Contributors: Alejandro Hernández Cordero, Shane Loretzclass_loaderInstall includes to include/ (#191)Fix include order for cpplint (#192)Update maintainers to Geoffrey Biggs and Michael Carroll (#190)Fix spelling mistake (#184)Contributors: Audrow Nash, David V. Lu!!, Jacob Perron, Shane Loretzcommon_interfacesUpdate maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow NashcompositionUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Additional fixes for documentation in demos. (#538)Fixing deprecated subscriber callback warnings (#532)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancettecomposition_interfacesUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashdemo_nodes_cppUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Add how to fix the most vexing parse problem (#541) * use uniform initializationFixing deprecated subscriber callback warnings (#532)Update talker_loaned_message.cpp (#518)Revert “Use sizeof(char) in place for sizeof(void) (#515)” (#516)change how serialized message works with subscription (#497)Use sizeof(char) in place for sizeof(void) (#515)Fix small print issue in allocator tutorial. (#509)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancette, Michel Hidalgo, Tomoya Fujita, William Woodall, Zongbao Fengdemo_nodes_cpp_nativeUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Fix typo in demo_nodes_cpp_native package description (#536)Contributors: Audrow Nash, Víctor Mayoral Vilchesdemo_nodes_pyCleanups in demo_nodes_py. (#555)Update maintainers to Audrow Nash and Michael Jeronimo (#543)Fixed typo executor -> executors (#542)Update python nodes SIGINT handling (#539)Contributors: Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, ori155diagnostic_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Greydomain_coordinatorUpdate maintainers to Michel Hidalgo (#13)Refactor domain_coordinator API to use a context manager (#12)Contributors: Audrow Nash, Timo Röhlingdummy_map_serverUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow Nashdummy_robot_bringupUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow Nashdummy_sensorsUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow Nashexample_interfacesUpdate maintainers to Mabel Zhang (#15)Add changelog (#14)Contributors: Audrow Nash, Ivan Santiago Paunovicexamples_rclcpp_async_clientUpdated maintainers (#329)Add example of how to prune old requests in client API (#322)Contributors: Aditya Pande, Ivan Santiago Paunovicexamples_rclcpp_cbg_executorImprove scheduling configuration of examples_rclcpp_cbg_executor package (#331)Added jitter measurement to examples_rclcpp_cbg_executor. (#328)Fix deprecated subscriber callbacks (#323)Remove use of get_callback_groups(). (#320)Contributors: Abrar Rahman Protyasha, Chris Lalancette, Ralph Langeexamples_rclcpp_minimal_action_clientUpdated maintainers (#329)Contributors: Aditya Pandeexamples_rclcpp_minimal_action_serverUpdated maintainers (#329)Contributors: Aditya Pandeexamples_rclcpp_minimal_clientUpdated maintainers (#329)Add example of how to prune old requests in client API (#322)Contributors: Aditya Pande, Ivan Santiago Paunovicexamples_rclcpp_minimal_compositionUpdated maintainers (#329)Contributors: Aditya Pandeexamples_rclcpp_minimal_publisherAdd an example about how to use wait_for_all_acked (#316)Updated maintainers (#329)Add try&catch statement to unique network flow publisher example (#313)Add type adaption example (#300)Contributors: Aditya Pande, Audrow Nash, Barry Xu, Tomoya Fujitaexamples_rclcpp_minimal_serviceUpdated maintainers (#329)Contributors: Aditya Pandeexamples_rclcpp_minimal_subscriberUseconst&signature for read-only sub callbacks (#337)Updated maintainers (#329)Fix deprecated subscriber callbacks (#323)Add wait set examples (#315)Add type adaption example (#300)Contributors: Abrar Rahman Protyasha, Aditya Pande, Audrow Nash, carlossvgexamples_rclcpp_minimal_timerUpdated maintainers (#329)Contributors: Aditya Pandeexamples_rclcpp_multithreaded_executorUpdated maintainers (#329)Fix deprecated subscriber callbacks (#323)Contributors: Abrar Rahman Protyasha, Aditya Pandeexamples_rclcpp_wait_setAdd wait set examples (#315)Contributors: carlossvgexamples_rclpy_executorsUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Update python nodes sigint/sigterm handling (#330)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovicexamples_rclpy_guard_conditionsUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Contributors: Aditya Pande, Audrow Nashexamples_rclpy_minimal_action_clientUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Contributors: Aditya Pande, Audrow Nashexamples_rclpy_minimal_action_serverUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Contributors: Aditya Pande, Audrow Nashexamples_rclpy_minimal_clientUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329) * Updated maintainers * Removed authorContributors: Aditya Pande, Audrow Nashexamples_rclpy_minimal_publisherUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Contributors: Aditya Pande, Audrow Nashexamples_rclpy_minimal_serviceUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Contributors: Aditya Pande, Audrow Nashexamples_rclpy_minimal_subscriberUpdate maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Contributors: Aditya Pande, Audrow Nashexamples_rclpy_pointcloud_publisherUpdate maintainers to Aditya Pande and Shane Loretz (#332)Contributors: Audrow Nashexamples_tf2_pyUpdate maintainers to Alejandro Hernandez Cordero and Chris Lalancette (#481)Use underscores instead of dashes in setup.cfg. (#403)Contributors: Audrow Nashfastrtps_cmake_moduleUpdate maintainers to Shane Loretz (#83)Contributors: Audrow Nashgeometry_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Greygoogle_benchmark_vendorAdd git buildtool dependency.Use git hash for google_benchmark_vendor (#20)Update to google benchmark version 1.6.1 (#19)Update maintainers to Audrow Nash (#18)Update google_benchmark to v1.5.3 (#16) 1. Change google_benchmark version from v1.5.2 to v1.5.3. Because v1.5.2 can not build with GCC 11 2. Removed shrink-tz-offset-size.patch because of this patch was merged in google-benchmark repo.Add changelog (#15)Shrink the size of the tz_offset variable. (#13)Update the patching to work on Windows without admin. (#11)Always preserve source permissions in vendor packages. (#12)Update package maintainers. (#10)Upgrade google benchmark from v1.5.1 to v1.5.2 to include QNX patch. (#9)Set the SOVERSION on benchmark libraries. (#8)Set minimum criteria for system package. (#3)Work around warnings building Google Benchmark w/Clang. (#2)Initial google_benchmark_vendor package. (#1)Initial commit.Contributors: Ahmed Sobhy, Audrow Nash, Chris Lalancette, Homalozoa X, Ivan Santiago Paunovic, Michel Hidalgo, Scott K Logan, Shane Loretz, Steven! Ragnarökimage_toolsInstall includes to include/${PROJECT_NAME} (#548)Fix include order and relative paths for cpplint (#551)Reduce the number of OpenCV libraries image_tools links against. (#549)Adds copy constructor and assignment operator to ROSCvMatContainer (#546)Fixes for uncrustify 0.72 (#545)Update maintainers to Audrow Nash and Michael Jeronimo (#543)Additional fixes for documentation in demos. (#538)Fixing deprecated subscriber callback warnings (#532)ambigulity: unknown type name ‘nullptr_t’ (#528)Add type masquerading demos (#482)Add support for visualizing yuv422 (#499)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancette, Gonzo, Jacob Perron, Shane Loretz, William Woodall, joshua-qnx, xwnbimage_transportImage transport publisher crash fixes (#235)Simple IT plugins shutdown (#225)Remove PLUGINLIB__DISABLE_BOOST_FUNCTIONS definition. (#226)Fix include order for cpplint (#221) Relates tohttps://github.com/ament/ament_lint/pull/324Export a modern CMake target instead of variables and install includes to include/${PROJECT_NAME} (#218)Fix SimpleSubscriberPlugin (#195)Make sure to mark overridden methods as ‘override’. (#192)Expose subscription options (#186)fix mistyping ‘cammera_publisher.hpp -> camera_publisher.hpp’ (#177)Update maintainers (#173)make CameraPublisher::getNumSubscribers() work (#163)Contributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Hye-Jong KIM, Ivan Santiago Paunovic, Jacob Perron, Michael Ferguson, RoboTech Vision, Shane Loretzinteractive_markersDo not publish if context is invalid during shutdown (#89)Install includes to include/ and misc CMake fixes (#85)Fix deprecation warning introduced after client API update (#83)Fix deprecated sub callback warnings (#84)Include tf2_geometry_msgs.hpp instead of the h file. (#82)Contributors: Abrar Rahman Protyasha, Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Shane Loretzintra_process_demoAdd opencv_imgproc dependency for cv::putText (#554)Install includes to include/${PROJECT_NAME} (#548)Fix include order and relative paths for cpplint (#551)Update maintainers to Audrow Nash and Michael Jeronimo (#543)Additional fixes for documentation in demos. (#538)Fixing deprecated subscriber callback warnings (#532)Revert “Add type masquerading demos (#482)” (#520)Add type masquerading demos (#482)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancette, Jacob Perron, Shane Loretz, William Woodallkdl_parserDepend on orocos-kdl vendor packages (#58)Install includes to include/ and misc CMake fixes (#61)Update to uncrustify 0.72 (#60)Contributors: Chris Lalancette, Jacob Perron, Shane Loretzlaser_geometryInstall headers to include/${PROJECT_NAME} (#86)Explicit cast to double to prevent loss of precisionFix Duration casting issue leading to no undistortionFix building on running on Windows Debug (#82)Update python code and tests for ros2 (#80)Contributors: Chris Lalancette, Jonathan Binney, Marco Lampacrescia, Shane LoretzlaunchSandbox environment in tests to fix repeated job failures (#609)Start Python faster in test_execute_processs_shutdown to avoid flakey failures (#608)Fix warnings from importlib_metdata on Python 3.10. (#606)Add boolean substitutions (#598)Support scoping environment variables (#601)Fix awaiting shutdown in launch context (#603)Fix parse respawn var (#569)Make the logged command pretty in ExecuteLocal (#594)‘output’ is expanded as a substitution in XML/YAML files (#577)Skip warning test if warning already happend (#585)Use asyncio.wait with timeout rather than sleep (#576)Make test_parser compatible with Python older than 3.8 (#575)Propagate exceptions of completed actions to launch service main loop (#566)Warn when loading launch extensions fails (#572)Add in two fixes for Jammy (#571)Evaluate math symbols and functions in python expression (#557)Document TimerAction params (#558)Improve launch arguments introspection (#556)Update maintainers to Aditya Pande and Michel Hidalgo (#559)Updated maintainers (#555)First prototype of native pytest plugin for launch based tests (#528)Allow for raw path specification in IncludeLaunchDescription (#544)Adding Executable description class (#454)event handlers: Allow to match the target action with a callable and not only with an object instance (#540)Add AppendEnvironmentVariable action (#543)Document EnvironmentVariable substitution resolution context caveat (#541)Feature clear launch configs (#515)Add examples to ExecuteProcess docs (#525)FixDeclareLaunchArgumentxml parsing and constructor (#529)Fix pytest run on Windows (#526)Improving docs (#523)Add filtering mechanism for executable prefix application (#522)Make each parser extension provide a set of file extensions (#516)Add missing exec dependency on PyYAML (#493)Refactor TimerAction to allow RosTimer to extend (#512)Improve (Not)Equals condition type hinting (#510)Contributors: Aditya Pande, Audrow Nash, Cameron Miller, Chris Lalancette, Christophe Bedard, David V. Lu!!, Derek Chopp, HMellor, Immanuel Martini, Ivan Santiago Paunovic, Jacob Perron, Kenji Miyake, Khush Jain, Kosuke Takeuchi, Rebecca Butler, Scott K Logan, Shane Loretz, roger-strain, tumtomlaunch_pytestUpdate maintainers to Aditya Pande and Michel Hidalgo (#559)[launch_pytest] Modify how wait_for_output()/wait_for_stderr() work, add assert_*() alternatives (#553)Updated maintainers (#555)[launch_pytest] Fix issue when colcon –retest-until-fail flag is used (#552)First prototype of native pytest plugin for launch based tests (#528)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunoviclaunch_rosFix importlib_metadata warning on Python 3.10. (#307)Use correct namespace when evaluating parameter files for composable nodes (#303)Handle empty strings when evaluating parameters (#300)Add parameter substitution (#297)fix bug in warning when an entry point fails to load (#243)More Helpful Error Messages (#275)Update maintainers in setup.py (#287)Set parameters from file for composable nodes (#281)Update package maintainers (#284)Update node name matcher (#282)Support both parameter file configurations for composable nodes (#259)Handle substitutions in RosTimer (#264)Add SetParametersFromFile action (#260)Properly support ros_args attribute through launch frontends (#253)Add ‘push_ros_namespace’ alias to ‘push-ros-namespace’ (#250)Add ros_arguments option to Node action (#249)Refactor RosTimer to extend TimerAction (#248)ROS Timer Action (#244)Support container in frontend (#235)Fix a small typo in a comment (#237)Better document parameter handling in Node (#234)Make ‘ros2 launch’ work again. (launch #201)Added LaunchLogger class (launch #145)Changed logger.warn (deprecated) to logger.warning. (launch #199)Added Plumb rclpy.init context to get_default_launch_description. (launch #193)Added normalize_parameters and evaluate_paramters. (launch #192)Added normalize_remap_rule and types. (launch #173)Renamed transitions to match changes inlifecycle_msgs(launch #153)Added support for passing parameters as a dictionary to a Node (launch #138)Made various fixes and added tests for remappings passed to Node actions (launch #137)Contributors: Aditya Pande, Audrow Nash, Chris Lalancette, Christophe Bedard, David V. Lu!!, Felix Divo, Jacob Perron, Kenji Miyake, Michel Hidalgo, Rebecca Butler, William Woodalllaunch_testingRemoved the deprecatedready_fnfeature (#589)Added case for instances of ExecuteLocal in resolveProcess function (#587)Add compatitibility with pytest 7 (#592)Renamed three files from example_processes (#573)Fix launch_testing README.md proc keyword to process. (#554) (#560)Declare frontend group dependency & use explicit dependencies in launch_testing (#520)Update maintainers to Aditya Pande and Michel Hidalgo (#559)Updated maintainers (#555)First prototype of native pytest plugin for launch based tests (#528)Adding Executable description class (#454)Add a “hello world” style example (#532)Contributors: Aditya Pande, Audrow Nash, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Khush Jain, Matt Lanting, Shane Loretz, William Woodall, roger-strainlaunch_testing_ament_cmake[launch_testing_ament_cmake] Add test label (#584)Update maintainers to Aditya Pande and Michel Hidalgo (#559)Updated maintainers (#555)Contributors: Aditya Pande, Audrow Nash, Keisuke Shimalaunch_testing_examplesReadded WaitForTopics utility (#333)Final batch of examples (#327)Update maintainers to Aditya Pande and Shane Loretz (#332)Updated maintainers (#329)Reverted WaitForTopics utility usage (#326)Moved examples (#324)Contributors: Aditya Pande, Audrow Nashlaunch_testing_rosAddhzparam totalker.pyto fix wait_for_topic_launch_test (#309)Revert WaitForTopics (#288)Update maintainers in setup.py (#287)Move pytest entrypoints to own module (#278)Update package maintainers (#284)Check that future is done, and always call rclpy.shutdown (#273)Revert “launch testing : Wait for topics to publish (#274)” (#276)Add WaitForTopics utility for waiting on publishers (#274)Remove unused code, Future.result() already raises (#270)Add timeout to wait for service response in example (#271)Add examples (#263)Contributors: Aditya Pande, Audrow Nash, Jacob Perron, Jorge Perez, Michel Hidalgo, Shane Loretzlaunch_xmlFix sphinx directive to cross-ref Launch method (#605)Add boolean substitutions (#598)Support scoping environment variables (#601)‘output’ is expanded as a substitution in XML/YAML files (#577)Declare frontend group dependency & use explicit dependencies in launch_testing (#520)Update maintainers to Aditya Pande and Michel Hidalgo (#559)Updated maintainers (#555)Add AppendEnvironmentVariable action (#543)Feature clear launch configs (#515)FixDeclareLaunchArgumentxml parsing and constructor (#529)Add ‘launch’ to sets of launch file extensions (#518)Make each parser extension provide a set of file extensions (#516)Contributors: Abrar Rahman Protyasha, Aditya Pande, Audrow Nash, Christophe Bedard, Derek Chopp, Ivan Santiago Paunovic, Jacob Perron, Kenji Miyake, Khush Jainlaunch_yamlFix sphinx directive to cross-ref Launch method (#605)Add boolean substitutions (#598)Support scoping environment variables (#601)‘output’ is expanded as a substitution in XML/YAML files (#577)Declare frontend group dependency & use explicit dependencies in launch_testing (#520)Update maintainers to Aditya Pande and Michel Hidalgo (#559)Updated maintainers (#555)Add AppendEnvironmentVariable action (#543)Feature clear launch configs (#515)Add ‘launch’ to sets of launch file extensions (#518)Make each parser extension provide a set of file extensions (#516)Contributors: Abrar Rahman Protyasha, Aditya Pande, Audrow Nash, Christophe Bedard, Derek Chopp, Jacob Perron, Kenji Miyake, Khush Jainlibcurl_vendorUpdate to curl 7.81. (#74)Update maintainers (#66)Contributors: Audrow Nash, Chris Lalancettelibstatistics_collectorBump pascalgn/automerge-action from 0.14.3 to 0.15.2Bump ros-tooling/setup-ros from 0.2.2 to 0.3.0Bump actions/upload-artifact from 2.3.1 to 3Bump actions/upload-artifact from 2.2.4 to 2.3.1Bump actions/checkout from 2 to 3Bump ros-tooling/setup-ros from 0.2.1 to 0.2.2 (#123)Install includes to include/${PROJECT_NAME} (#122)Bump codecov/codecov-action from 2.0.3 to 2.1.0Bump pascalgn/automerge-action from 0.14.2 to 0.14.3Bump codecov/codecov-action from 2.0.2 to 2.0.3Use rosidl_get_typesupport_target() (#116)Bump codecov/codecov-action from 2.0.1 to 2.0.2Bump codecov/codecov-action from 1.5.2 to 2.0.1Bump actions/upload-artifact from 1 to 2.2.4Bump codecov/codecov-action from 1.5.1 to 1.5.2Bump codecov/codecov-action from 1.3.1 to 1.5.1Bump ros-tooling/setup-ros from 0.2.0 to 0.2.1Bump pascalgn/automerge-action from 0.14.1 to 0.14.2Bump ros-tooling/setup-ros from 0.1 to 0.2.0Bump pascalgn/automerge-action from 0.13.1 to 0.14.1Fix autoapprovePackage.json explicitly owned by emerson to minimize notificationsBump hmarr/auto-approve-action from v2.0.0 to v2.1.0Bump codecov/codecov-action from v1.2.1 to v1.3.1Contributors: Chris Lalancette, Emerson Knapp, Shane Loretz, dependabot[bot]libyaml_vendorAdd a buildtool dependency on git. (#48)Install headers to include/${PROJECT_NAME} (#46)Merge pull request#43from ros2/update-maintainersUpdate maintainers to Audrow NashContributors: Audrow Nash, Shane Loretz, Steven! RagnaröklifecycleMake lifecycle demo automatically exit when done (#558)Use default on_activate()/on_deactivate() implemenetation of Node (#552)Update maintainers to Audrow Nash and Michael Jeronimo (#543)Fix use of future in lifecycle demo (#534)Fixing deprecated subscriber callback warnings (#532)Contributors: Abrar Rahman Protyasha, Audrow Nash, Christophe Bedard, Ivan Santiago Paunovic, Shane Loretzlifecycle_msgsUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashlifecycle_pyCreate changelog for lifecycle_pyAdd rclpy lifecycle demo (#547)Contributors: Audrow Nash, Ivan Santiago Paunoviclogging_demoUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Additional fixes for documentation in demos. (#538)Use rosidl_get_typesupport_target() (#529)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzmessage_filtersUse RCL_ROS_TIME for message_traits::TimeStamp (#72)Install includes to include/${PROJECT_NAME} (#71)Update maintainers (#67)Suppress rclcpp deprecation warnings in unit tests (#62)Add missing overrides to subscriber.h (#60)Add lifecycle node support (#59)Correct package.xml and CMakeLists.txt (#58)Expose Subscription Options - V2 (#56)Contributors: Abrar Rahman Protyasha, Audrow Nash, Hunter L. Allen, Kenji Brameld, Michel Hidalgo, Rebecca Butler, Shane Loretzmimick_vendorsupport pi zero (#24)Update maintainers to Geoffrey Biggs (#23)Update to latest commit for Apple M1 support (#20)Contributors: Audrow Nash, Brett Downing, Christophe Bedardnav_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Greypendulum_controlFix include order and relative paths for cpplint (#551)Remove the malloc_hook from the pendulum_demo. (#544)Update maintainers to Audrow Nash and Michael Jeronimo (#543)Additional fixes for documentation in demos. (#538)Fix documentation for pendulum_control. (#537)Contributors: Audrow Nash, Chris Lalancette, Jacob Perronpendulum_msgsUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Contributors: Audrow NashpluginlibInstall includes to include/${PROJECT_NAME} and remove ament_target_dependencies calls (#226)Require (#225)Move LibraryLoadExceptions down a level for more accurate error messages (#221)Update maintainers to Chris Lalancette (#223)extend termination condition to avoid infinite loop if package.xml is not found (#220)Remove deprecated headers. (#217)Contributors: Alberto Soragna, Audrow Nash, Chris Lalancette, David V. Lu!!, Shane Loretzpybind11_vendorUse sha256 hash instead of tag (#12)Install headers to include/${PROJECT_NAME} (#11)Update pybind11 to 2.7.1. (#10) This is the version that is shipped in Ubuntu 22.04.Contributors: Chris Lalancette, Shane Loretzpython_cmake_modulerequire Python 3.6 as we use format strings in various places (#10)Document all variables set by this module (#5)Add changelog (#4)Contributors: Ivan Santiago Paunovic, Shane Loretz, William Woodallqt_gui_cppInstall headers to include${PROJECT_NAME} (#259)Export targets instead of old-style CMake variables (#257)FindPython3 explicitly instead of FindPythonInterp implicitly (#254)Contributors: Shane Loretzquality_of_service_demo_cppInstall includes to include/${PROJECT_NAME} (#548)Fix include order and relative paths for cpplint (#551)Fixes for uncrustify 0.72 (#545)Update maintainers to Audrow Nash and Michael Jeronimo (#543)Additional fixes for documentation in demos. (#538)Fixing deprecated subscriber callback warnings (#532)Initialize message correctly (#522)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Shane Loretzquality_of_service_demo_pyUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Update python nodes SIGINT handling (#539)Contributors: Audrow Nash, Ivan Santiago Paunovicrcladd content-filtered-topic interfaces (#894)Add additional null check for timer argument (#973)Allow forward slashes within a parameter name rule in argument parsing (#860)Suppress false positive from clang-tidy (#951)Fix missing terminating 0 in rcl_context_impl_t.argv (#969)test_publisher_wait_all_ack depends on rcpputils (#968)Micro-optimizations in rcl (#965)If timer canceled, rcl_timer_get_time_until_next_call returns TIMER_CANCELED (#963)Add Events Executor (#839)Remove fastrtps customization on test_events (#960)Add client/service QoS getters (#941)introduce ROS_DISABLE_LOAN_MSG to disable can_loan_messages. (#949)Install includes it include/${PROJECT_NAME} (#959)Make rcl_difference_times args const (#955)Update inject_on_return test skipping logic (#953)Fix jump callbacks being called when zero time jump thresholds used (#948)Only change the default logger level if default_logger_level is set (#943)Add Library for wait_for_entity_helpers to deduplicate compilation (#942)Increase Windows timeout 15 -> 25 ms (#940)test should check specified number of entities. (#935)Fix up documentation build for rcl when using rosdoc2 (#932)Include rmw_event_t instead of forward declaring it (#933)Add rcl_publisher_wait_for_all_acked support. (#913)Add tracing instrumentation for rcl_take. (#930)Fix #include in C++ typesupport example in rcl_subscription_init docblock. (#927)Update includes after rcutils/get_env.h deprecation. (#917)Use proper rcl_logging return value type and compare to constant. (#916)Contributors: Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Haowei Wen, Ivan Santiago Paunovic, Jafar Abdi, Michel Hidalgo, Miguel Company, NoyZuberi, Scott K Logan, Shane Loretz, Tomoya Fujita, William Woodall, iRobot ROS, mauropassercl_actionAdd Events Executor (#839)Install includes it include/${PROJECT_NAME} (#959)Fix up documentation build for rcl_action when using rosdoc2 (#937)Fix expired goals capacity of action server (#931)Wait for action server in rcl_action comm tests. (#919)Contributors: Michel Hidalgo, Shane Loretz, iRobot ROS, spiralrayrcl_interfacesUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashrcl_lifecycleInstall includes it include/${PROJECT_NAME} (#959)[rcl_lifecycle] Do not share transition event message between nodes (#956)Update maintainers to Ivan Paunovic and William Woodall (#952)Fix up documentation build for rcl_lifecycle when using rosdoc2 (#938)Rename variable to fix name shadowing warning (#929)Contributors: Alberto Soragna, Audrow Nash, Ivan Santiago Paunovic, Michel Hidalgo, Shane Loretzrcl_logging_interfaceInstall includes to include/${PROJECT_NAME} (#85)Fix include order for cpplint (#84) Relates tohttps://github.com/ament/ament_lint/pull/324Update maintainers to Chris Lalancette (#83)Fix renamedrcpputilsheader (#81)Add Doxyfile to rcl_logging_interface package (#80)Update includes after rcutils/get_env.h deprecation (#75)Contributors: Abrar Rahman Protyasha, Audrow Nash, Christophe Bedard, Jacob Perron, Michel Hidalgo, Shane Loretzrcl_logging_noopUpdate maintainers to Chris Lalancette (#83)Contributors: Audrow Nashrcl_logging_spdlogFix include order for cpplint (#84) Relates tohttps://github.com/ament/ament_lint/pull/324Update maintainers to Chris Lalancette (#83)Fix renamedrcpputilsheader (#81)Update includes after rcutils/get_env.h deprecation (#75)Contributors: Abrar Rahman Protyasha, Audrow Nash, Christophe Bedard, Jacob Perronrcl_yaml_param_parserInstall includes it include/${PROJECT_NAME} (#959)Update maintainers to Ivan Paunovic and William Woodall (#952)Tweak rcl_yaml_param_parser documentation (#939)Contributors: Audrow Nash, Michel Hidalgo, Shane Loretzrclcppremove DEFINE_CONTENT_FILTER cmake option (#1914)remove things that were deprecated during galactic (#1913)add take_data_by_entity_id API to waitable (#1892)add content-filtered-topic interfaces (#1561)[NodeParameters] Set name in param info pre-check (#1908)Add test-dep ament_cmake_google_benchmark (#1904)Add publish by loaned message in GenericPublisher (#1856)Add missing ament dependency on rcl_interfaces (#1903)Update data callback tests to account for all published samples (#1900)Increase timeout for acknowledgments to account for slower Connext settings (#1901)clang-tidy: explicit constructors (#1782)Add client/service QoS getters (#1784)Fix a bunch more rosdoc2 issues in rclcpp. (#1897)time_until_trigger returns max time if timer is cancelled (#1893)Micro-optimizations in rclcpp (#1896)spin_all with a zero timeout. (#1878)Add RMW listener APIs (#1579)Remove fastrtps customization on tests (#1887)Install headers to include/${PROJECT_NAME} (#1888)Use ament_generate_version_header (#1886)use universal reference to support rvalue. (#1883)fix one subscription can wait_for_message twice (#1870)Add return value version of get_parameter_or (#1813)Cleanup time source object lifetimes (#1867)add is_spinning() method to executor base classCleanup the TypeAdapt tests (#1858)Cleanup includes (#1857)Fix include order and relative paths for cpplint (#1859)Rename stringstream in macros to a more unique name (#1862)Add non transform capabilities for intra-process (#1849)Fix rclcpp documentation build (#1779)Use UninitializedStaticallyTypedParameterException (#1689)Add wait_for_all_acked support (#1662)Add tests for function templates of declare_parameter (#1747)Fixes for uncrustify 0.72 (#1844)use private member to keep the all reference underneath. (#1845)Make node base sharable (#1832)Add Clock::sleep_for() (#1828)Synchronize rcl and std::chrono steady clocks in Clock::sleep_until (#1830)Use rclcpp::guard_condition (#1612)Call CMake function to generate version header (#1805)Use parantheses around logging macro parameter (#1820)Remove author by request (#1818)Update maintainers (#1817)min_forward & min_backward thresholds must not be disabled (#1815)Re-add Clock::sleep_until (#1814)Fix lifetime of context so it remains alive while its dependent node handles are still in use (#1754)Add the interface for pre-shutdown callback (#1714)Take message ownership from moved LoanedMessage (#1808)Suppress clang dead-store warnings in the benchmarks. (#1802)Wait for publisher and subscription to match (#1777)Fix unused QoS profile for clock subscription and make ClockQoS the default (#1801)Fix dangerous std::bind capture in TimeSource implementation. (#1768)Fix dangerous std::bind capture in ParameterEventHandler implementation. (#1770)Handle sigterm, in the same way sigint is being handled. (#1771)rclcpp::Node copy constructor: make copy of node_waitables_ member. (#1799)Extend NodeGraph to match what rcl provides. (#1484)Context::sleep_for(): replace recursion with do-while to avoid potential stack-overflow. (#1765)extend_sub_namespace(): Verify string::empty() before calling string::front(). (#1764)Deprecate thevoidshared_ptrsubscription callback signatures. (#1713)Remove can_be_nullptr assignment check for QNX case. (#1752)Update client API to be able to remove pending requests. (#1734)Fix: Allow to add a node while spinning in the StaticSingleThreadedExecutor. (#1690)Add tracing instrumentation for executor and message taking. (#1738)Fix: Reset timer trigger time before execute in StaticSingleThreadedExecutor. (#1739)Use FindPython3 and make python3 dependency explicit. (#1745)Use rosidl_get_typesupport_target(). (#1729)Fix returning invalid namespace if sub_namespace is empty. (#1658)Add free function to wait for a subscription message. (#1705)Use rcpputils/scope_exit.hpp and remove rclcpp/scope_exit.hpp. (#1727)Remove unsafe get_callback_groups API. Callers should change to using for_each_callback_group(), or store the callback groups they need internally.Add in callback_groups_for_each. The main reason to add this method in is to make accesses to the callback_groups_ vector thread-safe. By having a callback_groups_for_each that accepts a std::function, we can just have the callers give us the callback they are interested in, and we can take care of the locking. The rest of this fairly large PR is cleaning up all of the places that use get_callback_groups() to instead use callback_groups_for_each().Use a different mechanism to avoid timers being scheduled multiple times by the MultiThreadedExecutor (#1692)Fix windows CI (#1726) Fix bug in AnyServiceCallback introduced in#1709.Support to defer to send a response in services. (#1709) Signed-off-by: Ivan Santiago Paunovic Fix documentation bug. (#1719) Signed-off-by: William Woodall Removed left overis_initialized()implementation (#1711) Leftover fromhttps://github.com/ros2/rclcpp/pull/1622Fixed declare parameter methods for int and float vectors (#1696)Cleaned up implementation of the intra-process manager (#1695)Added the node name to an executorruntime_error(#1686)Fixed a typo “Attack” -> “Attach” (#1687)Removed use of std::allocator<>::rebind (#1678) rebind is deprecated in c++17 and removed in c++20Allow declare uninitialized parameters (#1673)Fix syntax issue with gcc (#1674)[service] Don’t use a weak_ptr to avoid leaking (#1668)Fix doc typo (#1663)[rclcpp] Type Adaptation feature (#1557)Do not attempt to use void allocators for memory allocation. (#1657)Keep custom allocator in publisher and subscription options alive. (#1647)Fix get_publishers_subscriptions_info_by_topic test in test_node.cpp (#1648)Use OnShutdown callback handle instead of OnShutdown callback (#1639)use dynamic_pointer_cast to detect allocator mismatch in intra process manager (#1643)Contributors: Abrar Rahman Protyasha, Ahmed Sobhy, Alberto Soragna, Andrea Sorbini, Audrow Nash, Barry Xu, Bi0T1N, Chen Lihui, Chris Lalancette, Christophe Bedard, Doug Smith, Emerson Knapp, Gaël Écorchard, Geoffrey Biggs, Gonzo, Grey, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Karsten Knese, Kenji Miyake, M. Hofstätter, M. Mostafa Farzan, Mauro Passerino, Michel Hidalgo, Miguel Company, Nikolai Morin, Petter Nilsson, Scott K Logan, Shane Loretz, Steve Macenski, Tomoya Fujita, William Woodall, Yong-Hao Zou, iRobot ROS, livanov93, mauropasserclcpp_actionremove things that were deprecated during galactic (#1913)add take_data_by_entity_id API to waitable (#1892)Fix rosdoc2 issues (#1897)Add RMW listener APIs (#1579)Install headers to include/${PROJECT_NAME} (#1888)Fix include order and relative paths for cpplint (#1859)Fixes for uncrustify 0.72 (#1844)Use rclcpp::guard_condition (#1612)Remove author by request (#1818)Update maintainers (#1817)Suppress clang dead-store warnings in the benchmarks. (#1802)Deprecate thevoidshared_ptrsubscription callback signatures (#1713)Use rcpputils/scope_exit.hpp and remove rclcpp/scope_exit.hpp. (#1727)Fixed occasionally missing goal result caused by race condition (#1677)Bump the benchmark timeout for benchmark_action_client (#1671)Returns CancelResponse::REJECT while goal handle failed to transit to CANCELING state (#1641)Fix action server deadlock issue that caused by other mutexes locked in CancelCallback (#1635)Contributors: Abrar Rahman Protyasha, Alberto Soragna, Chris Lalancette, Christophe Bedard, Jacob Perron, Kaven Yau, Shane Loretz, Tomoya Fujita, William Woodall, iRobot ROS, mauropasserclcpp_componentsSelect executor in node registration (#1898)Fix rosdoc2 issues in rclcpp (#1897)Fix bugprone-exception-escape in node_main.cpp.in (#1895)small improvements to node_main.cpp.inInstall headers to include/${PROJECT_NAME} (#1888)Use spin() in component_manager_isolated.hpp (#1881)add use_global_arguments for node options of component nodes (#1776)Add rclcpp_components::component (#1855)Add parameter to configure number of thread (#1708)remove RCLCPP_COMPONENTS_PUBLIC in class ComponentManagerIsolated (#1843)create component_container_isolated (#1781)Remove author by request (#1818)Update maintainers (#1817)Suppress clang dead-store warnings in the benchmarks. (#1802)Update client API to be able to remove pending requests. (#1734)Deprecate method names that use CamelCase in rclcpp_components. (#1716)Added a hook to generate node options in ComponentManager (#1702)Contributors: Alberto Soragna, Chris Lalancette, Daisuke Nishimatsu, Hirokazu Ishida, Ivan Santiago Paunovic, Jacob Perron, Rebecca Butler, Shane Loretz, gezprclcpp_lifecycleremove things that were deprecated during galactic (#1913)Fix rosdoc2 issues (#1897)Install headers to include/${PROJECT_NAME} (#1888)LifecycleNode::on_deactivate deactivate all managed entities. (#1885)Automatically transition lifecycle entities when node transitions (#1863)Remove author by request (#1818)Update maintainers (#1817)Suppress clang dead-store warnings in the benchmarks. (#1802)Update forward declarations ofrcl_lifecycletypes (#1788)Deprecate thevoidshared_ptrsubscription callback signatures (#1713)Update client API to be able to remove pending requests. (#1734)Change log level for lifecycle_publisher. (#1715)Fix: RCLCPP_PUBLIC -> RCLCPP_LIFECYCLE_PUBLIC (#1732)Use rcpputils/scope_exit.hpp and remove rclcpp/scope_exit.hpp (#1727)Remove unsafe get_callback_groups API. Callers should change to using for_each_callback_group(), or store the callback groups they need internally.Add in callback_groups_for_each. The main reason to add this method in is to make accesses to the callback_groups_ vector thread-safe. By having a callback_groups_for_each that accepts a std::function, we can just have the callers give us the callback they are interested in, and we can take care of the locking. The rest of this fairly large PR is cleaning up all of the places that use get_callback_groups() to instead use callback_groups_for_each().Fix destruction order in lifecycle benchmark (#1675)[rclcpp] Type Adaptation feature (#1557)Contributors: Abrar Rahman Protyasha, Alberto Soragna, Audrow Nash, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgo, Shane Loretz, Tomoya Fujita, William WoodallrclpyMake rclpy dependencies explicit (#906)Avoid exception in Node constructor when use override for ‘use_sim_time’ (#896)time_until_next_call returns max if timer is canceled. (#910)Properly implement action server/client handle cleanup. (#905)Make sure to take out contexts on Action{Client,Server}. (#904)Make sure to free the goal_status_array when done using it. (#902)Bugfix to Node.destroy_rate() result (#901)Remove fastrtps customization on tests (#895)fix typo (#890)Document that Future.result() may return None (#884)update doc release number (#885)Fix multi-threaded race condition in client.call_async (#871)Fix include order for cpplint (#877)Bugfix/duration to msg precision (#876)Update to pybind11 2.7.1 (#874)QoS history depth is only available with KEEP_LAST (#869)Implement managed nodes. (#865)Make rclpy.try_shutdown() behavior to follow rclpy.shutdown() more closely. (#868)Update TopicEndpointTypeEnum.__str__() method to include history kind and history depth. (#849)Add Clock.sleep_for() using Clock.sleep_until(). (#864)Add Clock.sleep_until() (#858)Add __enter__ and __exit__ to JumpHandle. (#862)Don’t override rclpy._rclpy_pybind11 docs. (#863)Improve JumpThreshold documentation and forbid zero durations. (#861)Fix time.py and clock.py circular import. (#860)Make context.on_shutdown() allow free functions. (#859)Fix automatically declared parameters descriptor type. (#853)Shutdown asynchronously when sigint is received. (#844)Update maintainers. (#845)Add entities to callback group before making them available to the executor to avoid a race condition. (#839)Avoid race condition in client.call(). (#838)Handle sigterm. (#830)Use pybind11 for signal handling, and delete now unused rclpy_common, pycapsule, and handle code. (#814)Fix memory leak in Service::take_request() and Client::take_response(). (#828)Add Publisher.wait_for_all_acked(). (#793)Only add one done callback to a future in Executor. (#816)Add convert function from ParameterValue to Python builtin. (#819)Call Context._logging_fini() in Context.try_shutdown(). (#800)Lift LoggingSeverity enum as common dependency to logging and rcutils_logger modules (#785)Set Context.__context to None in __init__(). (#812)Remove unused function make_mock_subscription. (#809)Removed common.c/h (#789)Allow declaring uninitialized parameters (#798)Reject cancel request if failed to transit to CANCEL_GOAL state (#791)Deleted handle as it should no longer be used (#786)Removed some functions in common.c and replaced them in utils.cpp (#787)Moved exception.cpp/hpp to the _rclpy_pybind11 module (#788)Print ‘Infinite’ for infinite durations in topic endpoint info (#722)Break log function execution ASAP if configured severity is too high (#776)Convert Node and Context to use C++ Classes (#771)Misc action server improvements (#774)Misc action goal handle improvements (#767)Convert Guardcondition to use C++ classes (#772)Removed unused structsrclpy_client_tandrclpy_service_t(#770)Convert WaitSet to use C++ Classes (#769)Convert ActionServer to use C++ Classes (#766)Convert ActionClient to use C++ classes (#759)Use py::class_ for rcl_action_goal_handle_t (#751)Convert Publisher and Subscription to use C++ Classes (#756)Rename QoS*Policy enum’s to *Policy (#379)Use params from node ‘/**’ from parameter YAML file (#370)Updated to use params from node ‘/**’ from parameter YAML file. (#399)Contributors: Alejandro Hernández Cordero, Anthony, Artem Shumov, Auguste Lalande, Barry Xu, Chris Lalancette, Emerson Knapp, Erki Suurjaak, Greg Balke, Ivan Santiago Paunovic, Jacob Perron, Lei Liu, Louise Poubel, Miguel Company, Shane Loretz, Tomoya Fujita, ksuszkarcpputilsInstall includes to include/${PROJECT_NAME} (#160)Fix include order for cpplint (#158)[path] Declare the default assignment operator (#156)Fixes for uncrustify 0.72 (#154)Fix the BSD license headers to use the standard one. (#153)Update maintainers to Chris Lalancette (#152)Add checked convert_to_nanoseconds() function (#145)Add missing sections in docs/FEATURES.md TOC (#151)[env] Addset_env_varfunction (#150)Add missing cstddef include (#147)Add accumulator test to CMakeLists.txt (#144)rcpputils::fs: Fix doxygen parameter identifier (#142)Make thread safety macro C++ standards compliant (#141)Fix API documentation for cleanrosdoc2build (#139)ImprovercppmathDoxygen documentation (#138)Improve documentation of utilities in docs/FEATURES.md (#137)Includercppmathutilities in docs/FEATURES.md (#136)FixIllegalStateExceptionreference in FEATURES (#135)migrate rolling mean from ros2_controllers to rcppmath (#133)Update includes after rcutils/get_env.h deprecation (#132)Contributors: Abrar Rahman Protyasha, Audrow Nash, Barry Xu, Chris Lalancette, Christophe Bedard, Jacob Perron, Karsten Knese, Octogonapus, Shane LoretzrcutilsUpdate launch test for change related to enviroment variables in launch (#354)Remove dst_size from strlen usage (#353)Install headers to include${PROJECT_NAME} (#351)Use static_cast instead of C-style cast (#349)Fixing up documentation build when using rosdoc2 (#344)Stop double-defining structs. (#333)Use FindPython3 explicitly instead of FindPythonInterp implicitly (#345)Fix build on Android (#342)Deprecate get_env.h and move content to env.{h,c} (#340)Contributors: Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Shane Loretz, William Woodallresource_retrieverInstall headers to include/${PROJECT_NAME} (#72)Fix include order for cpplint (#69)Update maintainers (#66)Remove the deprecated retriever.h header (#63)Contributors: Audrow Nash, Chris Lalancette, Jacob Perron, Shane LoretzrmwAdd content filtered topics support. (#302)Add sequence numbers to rmw_message_info_t. (#318)Add rmw_feature_supported(). (#318)Add EventsExecutor (#286)Document that rmw_wait() SHOULD use a monotonic clock (#316)Install headers to include/${PROJECT_NAME} (#317)Update rmw_server_is_available() API documentation. (#277)Add client/service QoS getters. (#314)Fix up documentation build for rmw when using rosdoc2 (#313)Fix up errors in doxygen documentation (#311)Fix copy-paste error in API doc for rmw_get_gid_for_publisher (#310)Add rmw_publisher_wait_for_all_acked support. (#296)Contributors: Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Michel Hidalgo, Shane Loretz, iRobot ROS, mauropassermw_connextddsExclude missing sample info fields when building rmw_connextddsmicro (#79)Update launch_testing_ros output filter prefixes for Connext6 (#80)Add support for user-specified content filters (#68)add stub for content filtered topic (#77)Add rmw listener apis (#44)Add client/service QoS getters. (#67)Add rmw_publisher_wait_for_all_acked support. (#20)Contributors: Andrea Sorbini, Barry Xu, Chen Lihui, Ivan Santiago Paunovic, iRobot ROS, mauropassermw_connextdds_commonExclude missing sample info fields when building rmw_connextddsmicro (#79)Properly initialize CDR stream before using it for filtering (#81)Add support for user-specified content filters (#68)add stub for content filtered topic (#77)Add sequence numbers to message info structure (#74)Add rmw listener apis (#44)Fix cpplint errors (#69)Add client/service QoS getters. (#67)Update rmw_context_impl_t definition (#65)Use the new rmw_dds_common::get_security_files API (#61)Add rmw_publisher_wait_for_all_acked support. (#20)Support extended signature formessage_type_support_callbacks_t::max_serialized_size()fromrosidl_typesupport_fastrtps_cpp. (#14)Update includes after rcutils/get_env.h deprecation. (#55)Always modify UserObjectQosPolicy regardless of override policy. (#53)Improved conversion of time values between ROS and DDS formats. (#43)Allow sharing DomainParticipant with C++ applications. (#25)Add environment variable to control override of DomainParticipantQos. (#41)Contributors: Andrea Sorbini, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgo, Miguel Company, iRobot ROS, mauropassermw_connextddsmicroExclude missing sample info fields when building rmw_connextddsmicro (#79)Add support for user-specified content filters (#68)add stub for content filtered topic (#77)Add sequence numbers to message info structure (#74)Add rmw listener apis (#44)Add client/service QoS getters. (#67)Add rmw_publisher_wait_for_all_acked support. (#20)Contributors: Andrea Sorbini, Barry Xu, Chen Lihui, Ivan Santiago Paunovic, iRobot ROS, mauropassermw_cyclonedds_cppFix get_topic_name and handling long service namesAdd serialization for SDK_DATAAdditional checks for loan APIDepend on just rmw_dds_common::rmw_dds_common_library (#385)Fix error message in rmw_init_options_copy(). (#380)Add content filter topic feature empty stub. (#289)Update to work with Cyclone 0.9.0 and Iceoryx 2.0 (#379)Fill message info sequence numbers as unsupported, add rmw_feature_supported() implementation. (#381)Fix a warning by making a pointer nullptr. (#375)Bump QDs to QL2 (#371)Add EventsExecutor (#256)Call dissociate_reader in rmw_destroy_subscriptionWrap creation of new serdata_rmw within a try-catch blockFix memory leak in error scenario on the publish side with SHMFix memory leaks on the take side with SHMrename _cyclonedds_has_shm to follow the conventionAdd iceoryx_binding_c as dependency to rmw_cyclonedds_cppRelease iox_chunk to iceoryx in serdata_free if the iox_chunk is still availableUpdate iceoryx_subscriber also when constructing the serdata from the iox chunkFix cpplint errors (#363)Updates for uncrustify 0.72 (#358)Export only rmw::rmw to downstream targets (#360)Export modern CMake targets (#357)Free with the same allocator in rmw_destroy_node (#355)Add client/service QoS getters. (#343)Updated version number and quality level. (#349)Update package maintainers. (#351)Fix undesired memory initialization in zero-copy data path. (#348)Fix QoS depth settings for clients/service being ignored. (#340)Link to Cyclone DDS in Quality Declaration. (#342)Update rmw_context_impl_t definition (#337)Add quality declaration for rmw_cyclonedds_cpp (#335)Fix use of deprecated is_loan_available (#336)Add -latomic for RISC-V (#332)Add pub/sub init, publish and take instrumentation using tracetools (#329)Pass the CRL down to CycloneDDS if it exists (#325)Use the new rmw_dds_common::get_security_files API (#323)Add rmw_publisher_wait_for_all_acked support. (#294)Fix zero copy issues. (#309)Handle allocation errors during message deserialization. (#313)Update includes after rcutils/get_env.h deprecation. (#312)Contributors: Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Dietrich Krönke, Erik Boasson, Haowei Wen, Ivan Santiago Paunovic, Jacob Perron, Joe Speed, Michel Hidalgo, Shane Loretz, Sumanth Nirmal, eboasson, guillaume-pais-siemens, iRobot ROS, mauropassermw_dds_commonDepend on target generated by rosidl_typesupport_cpp (#58)Use rosidl_get_typesupport_target() and target_link_libraries(). (#57)Install headers to include/${PROJECT_NAME} (#56)Fix include order for cpplint (#55)Fix up rmw_dds_common documentation when using rosdoc2 (#54)Add support for Certificate Revocation List files (#52)Silence clang warning (range-loop-construct) (#53)Add a common function for security files. (#51)Normalize rmw_time_t according to DDS spec (#48)Contributors: Andrea Sorbini, Chris Lalancette, Jacob Perron, Karsten Knese, Michel Hidalgo, Shane Loretzrmw_fastrtps_cppAdd pub/sub init, publish and take instrumentation using tracetools (#591)Add content filter topic feature (#513)Add sequence numbers to message info structure (#587)Removed some heap interactions in rmw_serialize.cpp (#590)Add EventsExecutor (#468)Install headers to include/${PROJECT_NAME} (#578)Add client/service QoS getters. (#560)Correctly recalculate serialized size on bounded sequences. (#540)Fix type size alignment. (#550)Change links from index.ros.org -> docs.ros.org (#539)Add rmw_publisher_wait_for_all_acked support. (#519)Loan messages implementation (#523) * Added is_plain_ attribute to base TypeSupport. * Added new methods to base TypeSupport. * Implementation of rmw_borrow_loaned_message. * Implementation of rmw_return_loaned_message_from_publisher. * Enable loan messages on publishers of plain types. * Implementation for taking loaned messages. * Enable loan messages on subscriptions of plain types.Contributors: Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Miguel Company, Shane Loretz, WideAwakeTN, iRobot ROS, mauropassermw_fastrtps_dynamic_cppAdd content filter topic feature (#513)Add sequence numbers to message info structure (#587)Add EventsExecutor (#468)Install headers to include/${PROJECT_NAME} (#578)Add client/service QoS getters. (#560)Correctly recalculate serialized size on bounded sequences. (#540)Fix type size alignment. (#550)Add rmw_publisher_wait_for_all_acked support. (#519)Loan messages implementation (#523) * Added is_plain_ attribute to base TypeSupport. * Added new methods to base TypeSupport. * Implementation of rmw_borrow_loaned_message. * Implementation of rmw_return_loaned_message_from_publisher. * Enable loan messages on publishers of plain types. * Implementation for taking loaned messages. * Enable loan messages on subscriptions of plain types.Contributors: Barry Xu, Chen Lihui, Ivan Santiago Paunovic, Miguel Company, Shane Loretz, iRobot ROS, mauropassermw_fastrtps_shared_cppAddress linter waning for windows. (#592)Add pub/sub init, publish and take instrumentation using tracetools (#591)Add content filter topic feature (#513)Add sequence numbers to message info structure (#587)Add EventsExecutor (#468)Complete events support (#583)Install headers to include/${PROJECT_NAME} (#578)Change default to synchronous (#571)Fix cpplint error (#574)Fixes for uncrustify 0.72 (#572)Add client/service QoS getters. (#560)Fix QoS depth settings for clients/service being ignored. (#564)Update rmw_context_impl_t definition. (#558)Update the LoanManager to do internal locking. (#552)Pass the CRL down to Fast-DDS if available. (#546)Use the new rmw_dds_common::get_security_files (#544)Support for SubscriptionOptions::ignore_local_publications (#536)Change links from index.ros.org -> docs.ros.org (#539)Add rmw_publisher_wait_for_all_acked support. (#519)Loan messages implementation (#523) * Added is_plain_ attribute to base TypeSupport. * Added new methods to base TypeSupport. * Implementation of rmw_borrow_loaned_message. * Implementation of rmw_return_loaned_message_from_publisher. * Enable loan messages on publishers of plain types. * Implementation for taking loaned messages. * Enable loan messages on subscriptions of plain types.Export rmw_dds_common as an rmw_fastrtps_shared_cpp dependency (#530)Update includes after rcutils/get_env.h deprecation (#529)Contributors: Audrow Nash, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Jose Antonio Moral, Michel Hidalgo, Miguel Company, Shane Loretz, Tomoya Fujita, iRobot ROS, mauropassermw_implementationadd content-filtered-topic interfaces (#181)Add rmw_feature_supported() (#204)Add EventsExecutor (#161)Fix relative path include syntax for cpplint (#203)Support and prefer exported targets from rmw implementations (#201)Add client/service QoS getters. (#196)Update maintainers to Audrow Nash and Michael Carroll. (#199)Fix renamedrcpputilsheader (#198)Fix rmw_implementation generated documentation (#197)Add rmw_publisher_wait_for_all_acked. (#188)Attempt to load any available RMW implementation. (#189)Update includes after rcutils/get_env.h deprecation (#190)Contributors: Abrar Rahman Protyasha, Audrow Nash, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Michel Hidalgo, Shane Loretz, iRobot ROS, mauropassermw_implementation_cmakeUse FastDDS as default DDS (#315)Contributors: Audrow Nashrobot_state_publisherDepend on orocos_kdl_vendor (#191)export dependencies, to use robot_state_publisher as a component (#193)Fix include order for cpplint (#186)Change how parameter updates are handled (#180)Install includes to instal/${PROJECT_NAME} (#184)Make the change_fixed_joint test more robust (#183)Add in a test to make sure fixed transforms change on updateSmall C++ nice-isms in the testsSwitch to using target_include_directories for testsPublish new fixed transforms when URDF is updatedMake joint_states subscription QoS configurable; default to SensorDataQoS (#179)Remove dependency on urdfdom_headers (#168)Fix deprecated subscriber callbacks (#173)Cleanup the documentation in the RobotStatePublisher class. (#172)Always publish fixed frames to /tf_static (#158)corrected publish_frequency default in README (#166)Add tf frame_prefix parameter (#159)Contributors: Abrar Rahman Protyasha, Anthony Deschamps, Chris Lalancette, Jacob Perron, Kenji Brameld, Nils Schulte, Russell Joyce, Shane Loretz, Steve Nogarros2actionAdd timeout to kill hanging tests (#701)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Shane Loretzros2bagsupport to publish as loaned message (#981)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)support to publish as loaned message (#981)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Bump version number to avoid conflictMake sure published messages are acknowledged for play mode (#951)TopicFilter use regex_search instead of regex_match (#932)Add start-offset play option (#931)Expose bag_rewrite asros2bagconvert(#921)Add “ignore leaf topics” option to recorder (#925)Auto-detect storage_id for Reader (if possible) (#918)Add pause/resume options to the bag recorder (#905)Add –start-paused option toros2bagplay(#904)Update package maintainers (#899)Fix converter plugin choices for record (#897)Add missing spaces to error message (#875)keyboard controls for pause/resume toggle and play-next: (#847)Add –snapshot-mode argument to the “record” verb (#851)Refactor plugin query mechanism and standardize trait management (#833)UpdatePlayOptions::delaytorclcpp::Durationto get nanosecond resolution (#843)Load compression and serialization choices via plugin query (#827)Add delay option (#789)Avoid passing exception KeyboardInterrupt to the upper layer (#788)Contributors: Abrar Rahman Protyasha, Audrow Nash, Barry Xu, Cameron Miller, Chris Lalancette, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Kosuke Takeuchi, Michel Hidalgo, Sonia Jin, Tony Pengros2cliFix importlib_metadata warning on Python 3.10. (#706)Add timeout to kill hanging tests (#701)Use try_shutdown() instead of shutdown() in DirectNode.__exit__() (#683)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Reapply#659(#661)Revert “Make the ros2cli output always line buffered (#659)” (#660)Make the ros2cli output always line buffered (#659)add uuid to ros2 daemon node name. (#658)Transfer daemon socket ownership on spawn. (#652)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Michel Hidalgo, Tomoya Fujitaros2cli_test_interfacesUpdate maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovicros2componentAdd timeout to kill hanging tests (#701)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Drop deprecated get_container_components_info() API. (#647)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Michel Hidalgoros2doctorFix importlib_metadata warning on Python 3.10. (#706)Add timeout to kill hanging tests (#701)Switch ros2 doctor to using psutil for network checks. (#687)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Improve ros2 doctor on Windows. (#631)Add QoS compatibility check and report. (#621)Contributors: Aditya Pande, Alberto Soragna, Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Shane Loretzros2interfaceAdd timeout to kill hanging tests (#701)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Shane Loretzros2launchUpdate maintainers in setup.py (#287)Use frontend group dependency & explicit dependencies in ros2launch (#256)Update package maintainers (#284)Add regex filter for selective launch-prefix application (#261)Resolves#37- Added –launch-prefix argument for ‘ros2 launch’ command (#254)Use sets of file extensions provided by parser extensions (#252)Simplify logic to fix absolute paths (#230)add way to include other Python launch files (launch #122)Contributors: Audrow Nash, Cameron Miller, Christophe Bedard, Michel Hidalgo, rob-clarkeros2lifecycleAdd timeout to kill hanging tests (#701)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Shane Loretzros2lifecycle_test_fixturesUpdate maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovicros2multicastAdd timeout to kill hanging tests (#701)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovicros2nodeAdd timeout to kill hanging tests (#701)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Shane Loretzros2paramAdd timeout to kill hanging tests (#701)Fix how ros2 param interprets command-line arguments. (#684)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Removed redundant code (#666)Reapply#659(#661)Fix flaky ros2 param list (#656)Skip None Result (#646)add ‘–write’ option to avoid an unintentional data loss. (#638)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Jacob Perron, Jay Wang, Tomoya Fujitaros2pkgAdd timeout to kill hanging tests (#701)Use local git config instead of global (#693)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)[ros2pkg] Skip copyright tests in template packages (#676)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Generate LICENSE files on ros2 pkg create. (#650)Handle ValueError (#643)Pass package exports to template in pkg create api (#619) (#628)Add changelogs (#635)Contributors: Abrar Rahman Protyasha, Aditya Pande, Amro Al-Baali, Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Shane Loretz, rob-clarke, tim-fanros2runAdd timeout to kill hanging tests (#701)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)check subprocess.returncode to print error message. (#639)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Tomoya Fujitaros2serviceAdd timeout to kill hanging tests (#701)Also provide –include-hidden-services forros2servicelistverb (#551)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Add changelogs (#635)Contributors: Aditya Pande, Audrow Nash, Ivan Santiago Paunovic, Karsten Knese, Shane Loretzros2testUse new domain_coordinator API (#10)Contributors: Timo Röhlingros2topicAdd timeout to kill hanging tests (#701)Add yaml dump flow style. (#698)support ros2topic echo once option. (#695)Fix special case for fastrtps incompatible QoS. (#694)Depend on launch packages instead of ros_testing to avoid circular dependency (#685)Add QoS history and depth information if available. (#678)Cleanup mislabeled BSD license (#447)Update maintainers to Aditya Pande, Audrow Nash, and Michael Jeronimo (#673)Updated maintainers (#670)Update lost messages test case (#669)Implementation of message filtering for ros2 (#654)Change default QoSProfile for pub (#653)Add option in ros2 topic pub to wait for N matching subscriptions, use N=1 by default when combined with –times (#642)ros2topicpubstarts publishing right away. (#626)Fix Topic Info Test with “Infinite” printing (#616)Add changelogs (#635)QoS autodetection (#613)Make Lost Messages option ON by default (#633)Contributors: Aditya Pande, Audrow Nash, Chris Lalancette, Emerson Knapp, Gonzo, Ivan Santiago Paunovic, Jorge Perez, Shane Loretz, Tomoya Fujita, Tully Foote, matthews-jcaros2traceFix ‘ros2 trace’ fini() errorDon’t require kernel tracer and detect when it’s not installedDeprecate ‘context_names’ param and replace with ‘context_fields’Contributors: Christophe Bedardrosbag2Bump version number to avoid conflictUpdate package maintainers (#899)Contributors: Chris Lalancette, Michel Hidalgorosbag2_compressionBump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Remove unnecessary public definition. (#950)Changes for uncrustify 0.72 (#937)Bugfix for broken bag split when using cache (#936)Update package maintainers (#899)Don’t preprocess a storage file more than once (#895)added seek interface (#836)Refactor plugin query mechanism and standardize trait management (#833)fix sequential reader rollover-to-next-file strategy: (#839)Load compression and serialization choices via plugin query (#827)Contributors: Cameron Miller, Chris Lalancette, Michael Orlov, Michel Hidalgo, Shane Loretz, soniarosbag2_compression_zstdBump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Update package maintainers (#899)Contributors: Chris Lalancette, Michel Hidalgo, Shane Loretzrosbag2_cppRevert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Bump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Remove unnecessary public definition. (#950)Fix relative path syntax for cpplint (#947)Mark up the message_cache with TSA annotations (#946)Changes for uncrustify 0.72 (#937)Redesign in cache consumer and circular message cache to get rid from busy loop (#941)Bugfix for broken bag split when using cache (#936)Remove JumpHandler copy-implementation from PlayerClock/TimeControllerClock (#935)Auto-detect storage_id for Reader (if possible) (#918)Add –start-paused option toros2bagplay(#904)Use the message_introspection header to get MessageMember. (#903)Update package maintainers (#899)Fix converter plugin choices for record (#897)Enable sanitizers only if code actually can run (#572)Need to pass introspection TS to converter plugin for it to be useful (#896)Don’t preprocess a storage file more than once (#895)Fix a bug on invalid pointer address when using “MESSAGE” compressio… (#866)Metadata per file info (#870)Fix TSA warnings when building with clang thread analysis. (#877)Implement snapshot mechanism and corresponding ROS Service (#850)Circular Message Cache implementation for snapshot feature (#844)Fix discovery silently stops after unknown msg type is found. (#848)added seek interface (#836)Refactor plugin query mechanism and standardize trait management (#833)fix sequential reader rollover-to-next-file strategy: (#839)Load compression and serialization choices via plugin query (#827)Workaround for false positive findings by clang thread safety analysis in time controller jump callbacks API. (#799)Add callbacks for PlayerClock::jump(time_point) API with CI fix (#779)Revert “Add callbacks for PlayerClock::jump(time_point) API (#775)” (#778)Add callbacks for PlayerClock::jump(time_point) API (#775)Contributors: Audrow Nash, Barry Xu, Cameron Miller, Chris Lalancette, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Lei Liu, Michael Orlov, Michel Hidalgo, Shane Loretz, Tony Peng, Wojciech Jaworski, soniarosbag2_interfacesBump version number to avoid conflictAdd burst-mode to Player (#977)Update package maintainers (#899)Implement snapshot mechanism and corresponding ROS Service (#850) * Add snapshot service to recorder node * Simplify and clarify double buffering patternsContributors: Cameron Miller, Chris Lalancette, Geoffrey Biggs, Michel Hidalgorosbag2_performance_benchmarkingBump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Enable YAML encoding/decoding for RecordOptions and StorageOptions (#916) * Enable YAML encoding/decoding for RecordOptions and StorageOptionsUpdate package maintainers (#899)Updated node declare_parameter to new syntax (#882)Updated benchmark package to use writer close() instead of old reset() (#881)Contributors: Adam Dąbrowski, Chris Lalancette, Emerson Knapp, Michel Hidalgo, Shane Loretzrosbag2_pysupport to publish as loaned message (#981)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)support to publish as loaned message (#981)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Bump version number to avoid conflictMake sure published messages are acknowledged for play mode (#951)Fix relative path syntax for cpplint (#947)Update to pybind11 2.7.1 (#945)Add start-offset play option (#931)Expose bag_rewrite asros2bagconvert(#921)Add “ignore leaf topics” option to recorder (#925)Add a ReaderWriterFactory utility to share logic for reuse (#923)Add pause/resume options to the bag recorder (#905)Add –start-paused option toros2bagplay(#904)Update package maintainers (#899)Fix converter plugin choices for record (#897)Metadata per file info (#870)keyboard controls for pause/resume toggle and play-next: (#847)Add –snapshot-mode argument to the “record” verb (#851)Add stopRecording into rosbag2_py (#854)added seek interface (#836)Refactor plugin query mechanism and standardize trait management (#833)UpdatePlayOptions::delaytorclcpp::Durationto get nanosecond resolution (#843)Load compression and serialization choices via plugin query (#827)Add delay option (#789)Handle SIGTERM gracefully in recording (#792)Contributors: Abrar Rahman Protyasha, Afonso da Fonseca Braga, Audrow Nash, Barry Xu, Cameron Miller, Chris Lalancette, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jorge Perez, Kosuke Takeuchi, Michel Hidalgo, Tony Peng, Wojciech Jaworski, soniarosbag2_storageRevert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Bump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Remove unnecessary public definition. (#950)Enable YAML encoding/decoding for RecordOptions and StorageOptions (#916)Update package maintainers (#899)Provide MetadataIO interface to convert metadata to a string in memory, alongside file IO versions (#894)Metadata per file info (#870)Implement snapshot mechanism and corresponding ROS Service (#850)added seek interface (#836)Refactor plugin query mechanism and standardize trait management (#833)Contributors: Audrow Nash, Cameron Miller, Chris Lalancette, Emerson Knapp, Jorge Perez, Michel Hidalgo, Shane Loretz, Tony Peng, Wojciech Jaworski, soniarosbag2_storage_default_pluginsBump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Emit a warning rather than crash when a message is too big for sqlite (#919)Enable YAML encoding/decoding for RecordOptions and StorageOptions (#916)Update package maintainers (#899)added seek interface (#836)Contributors: Chris Lalancette, Emerson Knapp, Michel Hidalgo, Shane Loretz, William Woodall, soniarosbag2_test_commonBump version number to avoid conflictInstall headers to include/${PROJECT_NAME} (#958)Update package maintainers (#899)Make sure the subscription exists before publishing messages (#804)Handle SIGTERM gracefully in recording (#792)Add spin_and_wait_for_matched to PublicationManager and update test c… (#797)Avoid passing exception KeyboardInterrupt to the upper layer (#788)Contributors: Barry Xu, Chris Lalancette, Emerson Knapp, Michel Hidalgo, Shane Loretzrosbag2_testsRevert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Revert “Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)” (#984)Add the ability to record any key/value pair in the ‘custom’ field in metadata.yaml (#976)Bump version number to avoid conflictAdd pause/resume options to the bag recorder (#905)Update package maintainers (#899)Fix a bug on invalid pointer address when using “MESSAGE” compressio… (#866)Metadata per file info (#870)Fix record test to reflect plugin query changes (#838)Make sure the subscription exists before publishing messages (#804)Handle SIGTERM gracefully in recording (#792)Add spin_and_wait_for_matched to PublicationManager and update test c… (#797)Remove rmw_fastrtps_cpp find_package in rosbag2_tests (#774)Contributors: Audrow Nash, Barry Xu, Cameron Miller, Chris Lalancette, Emerson Knapp, Ivan Santiago Paunovic, Jorge Perez, Michel Hidalgo, Tony Peng, Wojciech Jaworskirosbag2_transportsupport to publish as loaned message (#981)support to publish as loaned message (#981)Bump version number to avoid conflictAdd burst-mode to Player (#977)Install headers to include/${PROJECT_NAME} (#958)Make sure published messages are acknowledged for play mode (#951)Changes for uncrustify 0.72 (#937)TopicFilter use regex_search instead of regex_match (#932)Add start-offset play option (#931)Add parentheses suggested by Clang on OSX to fix build warning (#930)Bag rewriter (C++) (#920)Add “ignore leaf topics” option to recorder (#925)Rewrite TopicFilter for single-call reusability (#924)Add a ReaderWriterFactory utility to share logic for reuse (#923)Add pause/resume options to the bag recorder (#905)Add logging macros for rosbag2_transport (#917)Enable YAML encoding/decoding for RecordOptions and StorageOptions (#916)Expose the QoS object wrapper (#910)Add –start-paused option toros2bagplay(#904)Update package maintainers (#899)Add a Seek service (#874)Add simple keyboard control for playback rate (#893)Fix a bug on invalid pointer address when using “MESSAGE” compressio… (#866)Fix typo (#880)Use Reader’s seek() method for seeking/jumping in Player (#873)keyboard controls for pause/resume toggle and play-next: (#847)Implement snapshot mechanism and corresponding ROS Service (#850)Circular Message Cache implementation for snapshot feature (#844)Add jump/seek API for Player class (#826)Restructure test_play_timing to one test per case, to see which times out (#863)Fix discovery silently stops after unknown msg type is found. (#848)Fixing deprecated subscriber callback warnings (#852)Bugfix for race condition in Player::peek_next_message_from_queue() (#849)added seek interface (#836)UpdatePlayOptions::delaytorclcpp::Durationto get nanosecond resolution (#843)Move notification about ready for playback inside play_messages_from_queue() (#832)Add wait for player to be ready for playback in Player::play_next() method (#814)Make sure the subscription exists before publishing messages (#804)Add delay option (#789)Copy recorder QoS profile to local variable so that temporary value isn’t cleared (#803)test_play_services: fail gracefully on future error (#798)Recording with –all and –exclude fix (#765)Contributors: Abrar Rahman Protyasha, Audrow Nash, Barry Xu, Bastian Jäger, Cameron Miller, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Ivan Santiago Paunovic, Kosuke Takeuchi, Lei Liu, Louise Poubel, Michael Orlov, Michel Hidalgo, Piotr Jaroszek, Shane Loretz, soniarosgraph_msgsUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashrosidl_adapterrename nested loop index (#643)Fix how comments in action interfaces are processed (#632)Pass comments in ros interface constants to the .idl generated files (#630)Update package maintainers (#624)Make rosidl packages use FindPython3 instead of FindPythonInterp (#612)Fix escaping in string literals (#595)Ignore multiple#characters and dedent comments (#594)Contributors: Ivan Santiago Paunovic, Michel Hidalgo, Shane Loretz, ibnHatabrosidl_cliFix importlib_metdata warning with Python 3.10. (#674)Update maintainers to Michel Hidalgo and Shane Loretz (#633)Update package maintainers (#624)Support passing keyword arguments to rosidl CLI extensions (#597)Add missing f for format string (#600)Contributors: Audrow Nash, Chris Lalancette, Michel Hidalgo, Shane Loretzrosidl_cmakeMake rosidl_get_typesupport_target return -NOTFOUND instead of FATAL_ERROR (#672)Add introspection typesupport tests for C/C++ messages (#651)Use target output name for exporting typesupport library (#625)Update package maintainers (#624)Revert “Bundle and ensure the exportation of rosidl generated targets” (#611)Add rosidl_get_typesupport_target and deprecate rosidl_target_interfaces (#606)Bundle and ensure the exportation of rosidl generated targets (#601)Contributors: Jonathan Selling, Michel Hidalgo, Shane Loretzrosidl_default_generatorsUnroll group dependencies (#20)Contributors: Shane Loretzrosidl_default_runtimeUnroll group dependencies (#20)Contributors: Shane Loretzrosidl_generator_cFix error handling when copying C sequence messages (#671)Install generated headers to include/${PROJECT_NAME} (#670)Misc cleanup in the rosidl generator extensions (#662)Set the output size unconditionally when copying sequences (#669)Implement copy function for C messages (#650)Implement equality operator function for C messages. (#648)Generate documentation in generated C header files based on ROS interfaces comments (#593)Update package maintainers (#624)Make rosidl packages use FindPython3 instead of FindPythonInterp (#612)Revert “Bundle and ensure the exportation of rosidl generated targets” (#611)Bundle and ensure the exportation of rosidl generated targets (#601)Fix a cpplint allocator regression. (#590)Use RCUtils allocators in rosidl_generator_c (#584)Contributors: Chris Lalancette, Ivan Santiago Paunovic, Michel Hidalgo, Nikolai Morin, Pablo Garrido, Shane Loretzrosidl_generator_cppInstall generated headers to include/${PROJECT_NAME} (#670)Misc cleanup in the rosidl generator extensions (#662)Add missing build_export_depend dependency (#665)Fix bug where rosidl_runtime_cpp wasn’t depended upon (#660)Fix include order for cpplint (#644)Set CXX standard to 17 (#635)Update package maintainers (#624)Make rosidl packages use FindPython3 instead of FindPythonInterp (#612)Support flow style YAML printing (#613)Revert “Bundle and ensure the exportation of rosidl generated targets” (#611)Relocate to_yaml() under message namespace (#609)Bundle and ensure the exportation of rosidl generated targets (#601)Contributors: Jacob Perron, Jorge Perez, Michel Hidalgo, Shane Loretz, Øystein Sturerosidl_generator_dds_idlAdd changelog (#56)Contributors: Ivan Santiago Paunovicrosidl_generator_pyRemoves erroneous unmatched closing parenthesis (#125)require Python 3.6 as we use format strings in various places (#152)Fix rosidl_generator_py assuming incorect library names (#149)Fix for msg file containing a property field that is not at the end (#151)Update package maintainers (#147)Use rosidl_get_typesupport_target() (#139)Support available typesupport specification in CLI extension (#133)Use python_d for test_cli_extension in Debug mode (#136)Add missing float/double bounds check (#128)Added optimization for copying arrays using buffer protocol (#129)Add smoke test for CLI extension (#132)Install generated Python interfaces in a Python package (#131)Contributors: Charles Cross, Chen Lihui, Michel Hidalgo, Seulbae Kim, Shane Loretz, William Woodall, ksuszkarosidl_parserSet maybe_placeholders to False for lark 1.+ compatibility (#664)Generate documentation in generated C header files based on ROS interfaces comments (#593)Pass comments in ros interface constants to the .idl generated files (#630)Update package maintainers (#624)Fix escaping in string literals (#595)Contributors: Ivan Santiago Paunovic, Michel Hidalgo, Shane Loretzrosidl_runtime_cFix error handling when copying C sequence messages (#671)Set the output size unconditionally when copying sequences (#669)De-duplicate Quality Level from README and QUALITY_DECLARATION (#661)Install headers to include/${PROJECT_NAME} (#658)Implement copy function for C messages (#650)Implement equality operator function for C messages. (#648)Set CXX standard to 17 (#635)Update package maintainers (#624)Use RCUtils allocators in rosidl_generator_c (#584)Contributors: Jose Luis Rivero, Michel Hidalgo, Nikolai Morin, Pablo Garrido, Shane Loretz, Øystein Sturerosidl_runtime_cppAdd missing dependency on rosidl_runtime_c (#666)De-duplicate Quality Level from README and QUALITY_DECLARATION (#661)Install headers to include/${PROJECT_NAME} (#658)Set CXX standard to 17 (#635)Update package maintainers (#624)Contributors: Jose Luis Rivero, Michel Hidalgo, Shane Loretz, Øystein Sturerosidl_runtime_pyadd yaml dump flow style. (#16)Update maintainers (#15) * Update maintainers to Shane Loretz * Update Shane’s email Co-authored-by: Shane Loretz Contributors: Audrow Nash, Tomoya Fujitarosidl_typesupport_cUse target_link_libraries(… PRIVATE …) in single typesupport case (#124)rosidl CMake cleanup in rosidl_typesupport_c (#123)Install headers to include/${PROJECT_NAME} (#121)Use FindPython3 (#118)Revert “Bundle and ensure the exportation of rosidl generated targets” (#116)Support available typesupport specification in CLI extensions (#112)Bundle and ensure the exportation of rosidl generated targets (#113)Fix C and C++ typesupports CLI extensions (#111)Contributors: Michel Hidalgo, Shane Loretzrosidl_typesupport_cppUse target_link_libraries(… PRIVATE …) in single typesupport case (#124)rosidl CMake cleanup in rosidl_typesupport_cpp (#123)Install headers to include/${PROJECT_NAME} (#121)Make sure to check typesupport handles against nullptr properly (#119)Use FindPython3 (#118)Revert “Bundle and ensure the exportation of rosidl generated targets” (#116)Support available typesupport specification in CLI extensions (#112)Bundle and ensure the exportation of rosidl generated targets (#113)Fix C and C++ typesupports CLI extensions (#111)Contributors: Chris Lalancette, Michel Hidalgo, Shane Loretzrosidl_typesupport_fastrtps_cInstall generated headers to include/${PROJECT_NAME} (#88)Misc fastrtps typesupport generator cleanup (#87)Install headers to include/${PROJECT_NAME} (#86)Fix include order for cpplint (#84)Update maintainers to Shane Loretz (#83)Use FindPython3 explicitly instead of PythonInterp implicitly (#78)Revert rosidl targets and dependencies exportation (#76) * Revert “Export rosidl_typesupport_fastrtps_c* dependencies (#75)” * Revert “Bundle and ensure the exportation of rosidl generated targets (#73)”Correctly inform that a BoundedSequence is bounded (#71)Export rosidl_typesupport_fastrtps_c* dependencies (#75)Bundle and ensure the exportation of rosidl generated targets (#73)Fix Fast-RTPS C++ typesupport CLI extension (#72)Fastdds type support extensions (#67)Remove fastrtps dependency (#68)Contributors: Andrea Sorbini, Audrow Nash, Jacob Perron, Michel Hidalgo, Miguel Company, Shane Loretzrosidl_typesupport_fastrtps_cppInstall generated headers to include/${PROJECT_NAME} (#88)Misc fastrtps typesupport generator cleanup (#87)Install headers to include/${PROJECT_NAME} (#86)Fix include order for cpplint (#84) * Fix include order for cpplint Relates tohttps://github.com/ament/ament_lint/pull/324* Use double-quotes for other includes This is backwards compatible with older versions of cpplint.Update maintainers to Shane Loretz (#83)Re-introduce improvements to serialization of primitive bounded sequences for C++ type support (#81)Revert “Improve serialization of … (#79)” (#80)Improve serialization of primitive bounded sequences in C++ type support (#79)Use FindPython3 explicitly instead of PythonInterp implicitly (#78)Revert rosidl targets and dependencies exportation (#76) * Revert “Export rosidl_typesupport_fastrtps_c* dependencies (#75)” * Revert “Bundle and ensure the exportation of rosidl generated targets (#73)”Correctly inform that a BoundedSequence is bounded (#71)Export rosidl_typesupport_fastrtps_c* dependencies (#75)Bundle and ensure the exportation of rosidl generated targets (#73)Fix Fast-RTPS C++ typesupport CLI extension (#72)Fastdds type support extensions (#67)Remove fastrtps dependency (#68)Contributors: Andrea Sorbini, Audrow Nash, Jacob Perron, Jorge Perez, Michel Hidalgo, Miguel Company, Shane Loretzrosidl_typesupport_interfaceDe-duplicate Quality Level from README and QUALITY_DECLARATION (#661)Install headers to include/${PROJECT_NAME} (#658)Add ROSIDL_TYPESUPPORT_INTERFACE__LIBRARY_NAME() macro (#649)Set CXX standard to 17 (#635)Update package maintainers (#624)Contributors: Jose Luis Rivero, Michel Hidalgo, Shane Loretz, Øystein Sturerosidl_typesupport_introspection_cInstall generated headers to include/${PROJECT_NAME} (#670)Misc cleanup in the rosidl generator extensions (#662)De-duplicate Quality Level from README and QUALITY_DECLARATION (#661)Update Quality declaration to level 1 in README for instrospection pkgs (#659)Install headers to include/${PROJECT_NAME} (#658)Move rosidl_typesupport_introspection_cpp quality declaration to Q1 (#657)Move rosidl_typesupport_introspection_c quality declaration to Q1 (#656)add documentation for generators and API (#646)Rework nested types’ items introspection in C and C++ (#652)Fix up the documentation for rosidl_typesupport_introspection_c (#628)Update package maintainers (#624)Quality Declaration for typesupport_introspection (#621)Make rosidl packages use FindPython3 instead of FindPythonInterp (#612)Revert “Bundle and ensure the exportation of rosidl generated targets” (#611)Bundle and ensure the exportation of rosidl generated targets (#601)Update function prefix (#596)Contributors: Chris Lalancette, Jose Luis Rivero, Michel Hidalgo, Pablo Garrido, Shane Loretz, eboassonrosidl_typesupport_introspection_cppInstall generated headers to include/${PROJECT_NAME} (#670)Misc cleanup in the rosidl generator extensions (#662)De-duplicate Quality Level from README and QUALITY_DECLARATION (#661)Update Quality declaration to level 1 in README for instrospection pkgs (#659)Install headers to include/${PROJECT_NAME} (#658)Move rosidl_typesupport_introspection_cpp quality declaration to Q1 (#657)add documentation for generators and API (#646)Rework nested types’ items introspection in C and C++ (#652)Set CXX standard to 17 (#635)Fix up the documentation for rosidl_typesupport_introspection_cpp (#627)Update package maintainers (#624)Quality Declaration for typesupport_introspection (#621)Make rosidl packages use FindPython3 instead of FindPythonInterp (#612)Revert “Bundle and ensure the exportation of rosidl generated targets” (#611)Bundle and ensure the exportation of rosidl generated targets (#601)Contributors: Chris Lalancette, Jose Luis Rivero, Michel Hidalgo, Shane Loretz, eboasson, Øystein Sturerosidl_typesupport_introspection_testsBumprosidl_typesupport_introspection_testscoverage (#655)Add introspection typesupport tests for C/C++ services (#653)Add introspection typesupport tests for C/C++ messages (#651)Contributors: Michel HidalgorpyutilsMake sure to call abspath when adding Windows DLL directories. (#8)Update troubleshooting links to docs.ros.org (#6)Contributors: Chris Lalancette, Christophe Bedardrqt_guiChanged getiter to iter (#1) (#241)Update maintainers (#233) (#237)add missing dependencies: rospkg-modules, python_qt_binding, rospy (#227)bump CMake minimum version to avoid CMP0048 warning (#219)use catkin_install_python for Python script (#206)Contributors: Michael Jeronimo, sven-herrmannrqt_gui_cppUpdate maintainers (#233) (#237)bump CMake minimum version to avoid CMP0048 warning (#219)[Windows] fix rqt_gui_cpp install path (#190)[Windows] fix building (#189)Contributors: Michael Jeronimorqt_gui_pyUpdate maintainers (#233) (#237)bump CMake minimum version to avoid CMP0048 warning (#219)rqt_py_commonUpdate maintainers (#233) (#237)bump CMake minimum version to avoid CMP0048 warning (#219)fix missing import bugs (#139)Contributors: Michael Jeronimorti_connext_dds_cmake_moduleUpdate rti-connext-dds dependency to 6.0.1. (#71)Contributors: Steven! RagnarökrttestInstall includes to include/${PROJECT_NAME} (#114)Fix include order for cpplint (#113)Fixes for uncrustify 0.72 (#111)Mark dependent targets as PRIVATE (#112)Export modern CMake targets (#110)Contributors: Chris Lalancette, Jacob Perron, Shane Loretzrviz2Change links index.ros.org -> docs.ros.org. (#698)Contributors: Chris Lalancetterviz_assimp_vendorMake sure to pass compiler and flags down to assimp (#844)Fix support for assimp 5.1.0 (#817)Contributors: Chris Lalancette, Silvio Traversarorviz_commonAdd implementation for cancel interface (#809)Install headers to include/${PROJECT_NAME} (#829)Remove definition of PLUGINLIB_DISABLE_BOOST. (#821)Fix support for assimp 5.1.0 (#817)Fix cpplint errors (#818)Set message type for ros topic display (#800)Fixes for uncrustify 0.72 (#807)Do not block visualization manager updates when opening the display panel dialog (#795)Switch to using Qt::MiddleButton for RViz. (#802)Removed traces in renderPanel (#777)move yaml_config_writer.hpp to public includes (#764)Update displays_panel.cpp (#745)Robot: Report mesh loading issues (#744)Exposed tool_manager header file. (#767)refactor: make const getter methods const (#756)Efficiently handle 3-bytes pixel formats (#743)Report sample lost events (#686)Update window close icon (#734)Fix missing “X” icon in panel close button (#731)Add rviz_rendering dependency to rviz_common (#727)Remove the word “Alpha” from the splash screen. (#696)Removed some memory leaks in rviz_rendering and rviz_rendering_tests (#710)Contributors: ANDOU Tetsuo, Alejandro Hernández Cordero, Chen Lihui, Chris Lalancette, Daisuke Nishimatsu, Gonzo, Ivan Santiago Paunovic, Jacob Perron, Joseph Schornak, Rebecca Butler, Shane Loretz, Silvio Traversaro, davidorchanskyrviz_default_pluginsAdd far plane distance property to camera (#849)Drop ignition-math6 from rviz_default_plugins link interface (#833)add implementation for cancel interface (#809)Install headers to include/${PROJECT_NAME} (#829)Remove definition of PLUGINLIB_DISABLE_BOOST. (#821)Remove TF filter from ImageTransportDisplay (#788)Add underscores to material names (#811)Export image_transport dependency (#813)Fixes for uncrustify 0.72 (#807)Switch to using Qt::MiddleButton for RViz. (#802)Add a tf_buffer_cache_time_ns to tf_wrapper (#792)Make libraries to avoid compiling files multiple times (#774)Computed inertia with ignition-math (#751)Fixed crash when changing rendering parameters for pointcloud2 while ‘Selectable’ box is unchecked (#768)Robot: Report mesh loading issues (#744)Handle NaN values for Wrench msgs (#746)Triangle lists support textures (#719)Report sample lost events (#686)Fix path message orientation error (#736)Set topic namespace in interactive markers display (#725)mass property visualization (#714)Export InteractiveMarker (#718)Yuv to rgb changes (#701)Extract message type in ImageTransportDisplay (#711)Duplicated code RobotJoint (#702)Don’t attempt to moc generate files that don’t have QOBJECT. (#690)Switch to including tf2_geometry_msgs.hpp (#689)Export Qt5 dependencies properly (#687)Add support for namespace-scoped DELETEALL action in Marker displays (#685)Use image_transport to subscribe to image messages (#523)Contributors: Akash, Alejandro Hernández Cordero, Audrow Nash, Chen Lihui, Chris Lalancette, Cory Crean, Gonzo, Greg Balke, Ivan Santiago Paunovic, Jacob Perron, Martin Idel, Michel Hidalgo, Paul, Rebecca Butler, Scott K Logan, Shane Loretz, bailaC, brian soe, cturcotte-qnx, ketatamrviz_ogre_vendorFix interface link libraries in ogre vendor (#761)Fix the build for Ubuntu Jammy arm64. (#828)Strip RPATH from installed Ogre binaries (#688)Contributors: Chris Lalancette, Laszlo Turanyi, Michel Hidalgorviz_renderingMake getVerticesPerPoint method public and improve tests (#843)Disable class-memaccess warnings for Eigen (#838)Disable a warning when including Eigen. (#835)Install headers to include/${PROJECT_NAME} (#829)Fix support for assimp 5.1.0 (#817)Fix cpplint errors (#818)Fixes for uncrustify 0.72 (#807)Suppress assimp warnings in rviz_rendering build (#775)Fix for ogre failing when material already exists (#729)Removed some memory leaks in rviz_rendering and rviz_rendering_tests (#710)Export Qt5 dependencies properly (#687)Putting glsl 1.50 resources back in RenderSystem (#668)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jacob Perron, Jorge Perez, Michel Hidalgo, Piotr Jaroszek, Scott K Logan, Shane Loretz, Silvio Traversaro, Wolf Vollprechtrviz_rendering_testsRemoved some memory leaks in rviz_rendering and rviz_rendering_tests (#710)Contributors: Alejandro Hernández Corderorviz_visual_testing_frameworkInstall headers to include/${PROJECT_NAME} (#829)Fixes for uncrustify 0.72 (#807)Update includes after rcutils/get_env.h deprecation (#677)Contributors: Chris Lalancette, Christophe Bedard, Shane Loretzsensor_msgsMove the find_package statements for BUILD_TESTING (#186)Feedback on conditional sensor_msgs_library target (#1) (#183)[Fix] Fix image_encodings.hpp’s URL in README (#184)[Fix] Fix fill_image.hpp’s URL in README (#182)Add sensor_msgs_library target and install headers to include/${PROJECT_NAME} (#178)Interface packages should fully on the interface packages that they depend on (#173)Add YUV420 and YUV444 to image encodings (#172)Cleanup mislabeled BSD license (#83)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Fix rosdoc2 warnings in sensor_msgs. (#162)Add equidistant distortion model (#160)Use rosidl_get_typesupport_target() (#156)Update CompressedImage documentation: add ‘tiff’ as a supported format (#154)Contributors: Audrow Nash, Chris Lalancette, Grey, Hemal Shah, Homalozoa X, Ivan Santiago Paunovic, Martin Günther, Michael Jeronimo, Pablo Garrido, Shane Loretz, Tully Footesensor_msgs_pyAdd in a compatibility layer for older versions of numpy. (#185)Port pointcloud creation to numpy. (#175)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Chris Lalancette, Florian Vahlshape_msgsInterface packages should fully on the interface packages that they depend on (#173)Add prism type to the SolidPrimitive.msg (#166) (#167)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Grey, M. Fatih Cırıtshared_queues_vendorBump version number to avoid conflictUpdate package maintainers (#899)Contributors: Chris Lalancette, Michel Hidalgosqlite3_vendorBump version number to avoid conflictUpdate package maintainers (#899)Contributors: Chris Lalancette, Michel Hidalgosros2Increase the shutdown timeout for test_generate_policy_no_nodes. (#278)Contributors: Chris Lalancettestatistics_msgsUpdate maintainers to Chris Lalancette (#130)Contributors: Audrow Nashstd_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Greystd_srvsUpdate maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nashstereo_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, Greytest_cliUpdated maintainers (#489)Add changelogs (#473)Merge pull request#356from ros2/issue/321_enhance_parameter_apiContributors: Aditya Pande, Ivan Santiago Paunovictest_cli_remappingUpdate python nodes SIGINT handling (#490)Updated maintainers (#489)Add changelogs (#473)Contributors: Aditya Pande, Ivan Santiago Paunovictest_communicationSplit test_subscriber into multiple compilation units. (#500)Add test_msgs dependency (#497)Update python nodes SIGINT handling (#490)Updated maintainers (#489)Fix deprecated subscriber callback warnings (#483)Add tests for BoundedPlainSequences (#481)Use rosidl_get_typesupport_target() (#480)Use rcpputils/scope_exit.hpp instead of rclcpp/scope_exit.hpp (#479)Add changelogs (#473)Contributors: Abrar Rahman Protyasha, Aditya Pande, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Shane Loretztest_interface_filesRevert “Update package.xml (#18)” (#19)Update package.xml (#18)Update maintainers to Audrow Nash (#17)Added BoundedPlainSequences messages (#14)Contributors: Audrow Nash, Chris Lalancette, Miguel Company, Nikolai Morintest_launch_rosIncrease test time tolerance (#305)Use correct namespace when evaluating parameter files for composable nodes (#303)Handle empty strings when evaluating parameters (#300)Add parameter substitution (#297)More Helpful Error Messages (#275)Update maintainers in setup.py (#287)Set parameters from file for composable nodes (#281)Update package maintainers (#284)Update node name matcher (#282)Support both parameter file configurations for composable nodes (#259)Shutdown context after test (#267)Handle substitutions in RosTimer (#264)Add SetParametersFromFile action (#260)Properly support ros_args attribute through launch frontends (#253)Add ‘push_ros_namespace’ alias to ‘push-ros-namespace’ (#250)Add ros_arguments option to Node action (#249)ROS Timer Action (#244)Support container in frontend (#235)Added normalize_remap_rule and types. (launch #173)Fixed setup.py versions (launch #155)Fixed a bug to ensure that shutdown event is handled correctly (launch #154)Made various fixes and added tests for remappings passed to Node actions (launch #137)Contributors: Aditya Pande, Audrow Nash, Christophe Bedard, David V. Lu!!, Jacob Perron, Jorge Perez, Kenji Miyake, Michel Hidalgo, Rebecca Butlertest_launch_testingUpdate maintainers to Aditya Pande and Michel Hidalgo (#559)Updated maintainers (#555)Contributors: Aditya Pande, Audrow Nashtest_msgsInstall headers to include/${PROJECT_NAME} and Depend on rosidl_typesupport_* targets directly (#133)Update maintainers to Chris Lalancette (#130)Add test fixures for BoundedPlainSequences (#125)Added BoundedPlainSequences to test_msgs (#123)Contributors: Audrow Nash, Miguel Company, Shane Loretztest_quality_of_serviceUpdate maintainers to Aditya Pande and Shane Loretz (#491)Updated maintainers (#489)Fix deprecated subscriber callback warnings (#483)Add changelogs (#473)Contributors: Abrar Rahman Protyasha, Aditya Pande, Audrow Nash, Ivan Santiago Paunovictest_rclcppFix include order for cpplint (#493)Fix test (#488)Updated maintainers (#489)Add tests for rclcpp sigterm handler (#485)Fix deprecated subscriber callback warnings (#483)Fix deprecation warnings and failures after client API update (#482)Use rosidl_get_typesupport_target() (#480)Use rcpputils/scope_exit.hpp instead of rclcpp/scope_exit.hpp (#479)Add test for defered service callback signature (#478)Add changelogs (#473)Merge pull request#357from ros2/ros2_658_leftoversContributors: Abrar Rahman Protyasha, Aditya Pande, Christophe Bedard, Ivan Santiago Paunovic, Jacob Perron, Mauro Passerino, Shane Loretztest_rmw_implementationadd content-filtered-topic interfaces (#181)Fix linter issues (#200)Add client/service QoS getters. (#196)Added tests for bounded sequences serialization (#193)Add RMW_DURATION_INFINITE basic compliance test. (#194)Test SubscriptionOptions::ignore_local_publications. (#192)Add rmw_publisher_wait_for_all_acked. (#188)Wait for server in test_rmw_implementation service tests. (#191)Contributors: Barry Xu, Chen Lihui, Emerson Knapp, Jorge Perez, Jose Antonio Moral, Michel Hidalgo, Miguel Company, mauropassetest_securityUpdated maintainers (#489)Fix deprecated subscriber callback warnings (#483)Add changelogs (#473)Simplify the test_secure_subscriber code. (#471)Update includes after rcutils/get_env.h deprecation (#472)Contributors: Abrar Rahman Protyasha, Aditya Pande, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovictest_tf2Fix more instances of Eigen problems on RHEL. (#515)Install includes to include/${PROJECT_NAME} and use modern CMake (#493)Fix precision loss from using rclcpp::Time::seconds() (#511)More Intuitive CLI for Static Transform Publisher (#392)Conversion tests for toMsg() (#423)Deprecate tf2_geometry_msgs.h (#418)Deprecate tf2_kdl.h (#414)Deprecate tf2_bullet.h (#412)Contributors: Bjar Ne, Chris Lalancette, Hunter L. Allen, Kenji Brameld, Shane Loretztest_tracetoolsIntroduce constants for tracepoint namesMove actual tests out of tracetools_test to new test_tracetools packageContributors: Christophe Bedardtest_tracetools_launchAdd support for preloading pthread and dl instrumentation shared libsRemove profile_fast option and consider LD_PRELOADing both libsFix multiple LdPreload actions not working and add testDeprecate ‘context_names’ param and replace with ‘context_fields’Move some tests from tracetools_launch to test_tracetools_launchContributors: Christophe Bedard, Ingo Lütkebohletf2Install includes to include/${PROJECT_NAME} and use modern CMake (#493)forward declare fromMsg to avoid missing symbols in downstream libraries (#485)tf2: Enable common linter tests (#469)Move time functions into time.cpp.Change a for loop to a while loop.Switch to C++-style casts.Remove totally unused (and unreachable) code.Replace NULL with nullptr.Fix up some comments.Use std::make_shared where we can.Replace two comparisons with empty string to empty().Make sure to include-what-you-use.Remove unnecessary internal method.Remove long-deprecated walkToTopParent overload.Remove unnecessary test dependencies.Remove some references to the ROS 1 wiki.Add rosidl_runtime_cpp as build_depend and build_export_depend.Minor cleanups in CMakeLists.txt.Remove include directory that doesn’t exist.Remove completely unnecessary target_link_libraries.Remove unused speed_test from tf2.Suppress clang warnings about enumerator attributes. (#463)Change TF2Error names to be a bit more descriptive. (#349)Fixed errors due to missing header link. (#432)Deprecate tf2_geometry_msgs.h (#418)Speedup covariance unwrapping (#399)Contributors: Abrar Rahman Protyasha, Chris Lalancette, Dima Dorezyuk, João C. Monteiro, Shane Loretz, Shivam Pandeytf2_bulletInstall includes to include/${PROJECT_NAME} and use modern CMake (#493)Export a tf2_bullet::tf2_bullet target (#495)Fix cpplint errors (#497)Remove some references to the ROS 1 wiki.Fix tf2_bullet dependency export (#428)Deprecate tf2_bullet.h (#412)Contributors: Bjar Ne, Chris Lalancette, Jacob Perron, Shane Loretztf2_eigenWorkaround broken RHEL FindEigen3.cmake (#513)Install includes to include/${PROJECT_NAME} and use modern CMake (#493)Disable mem-access warnings on aarch64. (#506)Fix cpplint errors (#497)Remove some references to the ROS 1 wiki.Add doTransform function for twists or wrenches (#406)Reenable stamped eigen tests (#429)Deprecate tf2_eigen.h (#413)Contributors: AndyZe, Bjar Ne, Chris Lalancette, Jacob Perron, Shane Loretztf2_eigen_kdlFix more instances of Eigen problems on RHEL. (#515)Depend on orocos_kdl_vendor (#473)Install includes to include/${PROJECT_NAME} and use modern CMake (#493)Fix cpplint errors (#497)Contributors: Chris Lalancette, Jacob Perron, Shane Loretztf2_geometry_msgsMake sure to find the right Python executable. (#514)Depend on orocos_kdl_vendor (#473)Install includes to include/${PROJECT_NAME} and use modern CMake (#493)Drop PyKDL dependency in tf2_geometry_msgs (#509)Fix cpplint errors (#497)Export a tf2_geometry_msgs::tf2_geometry_msgs target (#496)Feature: Add doTransform for Wrench messages (#476)Remove some references to the ROS 1 wiki.Style fixes in tf2_geometry_msgs. (#464)Fix for issue#431- Covariance is not transformed in do_transform_pose_with_covariance_stamped (#453)doTransform non stamped msgs (#452)tf2_geometry_msgs: Fixing covariance transformation indoTransform(#430)Geometry nitpicks (#426)Conversion tests for toMsg() (#423)Deprecate tf2_geometry_msgs.h (#418)Contributors: Abrar Rahman Protyasha, Bjar Ne, Chris Lalancette, Denis Štogl, Florian Vahl, Jacob Perron, Khasreto, Shane Loretz, vineet131tf2_kdlDepend on orocos_kdl_vendor (#473)Install includes to include/${PROJECT_NAME} and use modern CMake (#493)KDL python formatting and licenses (#425)Deprecate tf2_kdl.h (#414)Contributors: Bjar Ne, Chris Lalancette, Jacob Perron, Shane Loretztf2_msgsRemove dead file from tf2_msgs (#415)Contributors: Chris Lalancettetf2_pyMake sure to finalize tf2_py BufferCore. (#505)Make tf2_py Use FindPython3 (#494)Change TF2Error names to be a bit more descriptive. (#349)Remove python_compat.h (#417)Contributors: Chris Lalancette, Shane Loretztf2_rosInstall includes to include/${PROJECT_NAME} and use modern CMake (#493)use dedicated callback group and executor to isolate timer (#447)Adding shared pointer definition to tf2 buffer (#508)fix for a basic logic (#510)Fix precision loss from using rclcpp::Time::seconds() (#511)clear relative callback of Buffer if MessageFilter is destroyed (#490)More info in tf2_echo output (#468)Fix cpplint errors (#497)Fixes for uncrustify 0.72 (#486)More Intuitive CLI for Static Transform Publisher (#392)Reduce transform listener nodes (#442)tf2_ros: Fix deprecated subscriber callbacks (#448)Fix tf2_echo does not work with ros-args (#407) (#408)Contributors: Abrar Rahman Protyasha, Chen Lihui, Chris Lalancette, Hunter L. Allen, Jacob Perron, Kenji Brameld, PGotzmann, Shane Loretz, Steve Macenski, Zhenpeng Ge, gezp, simulacrustf2_ros_pyDrop PyKDL dependency in tf2_geometry_msgs (#509)Add in one more destroy call that was missed in testing. (#504)Be much more careful about cleanup in the tf2_ros_py tests. (#499)Use the correct type for BufferClient timeout_padding. (#498) It should be a duration, not a float.Update maintainers to Alejandro Hernandez Cordero and Chris Lalancette (#481)Fix buffer_client.py using default timeout_padding (#437)Use underscores instead of dashes in setup.cfg. (#403)Contributors: Audrow Nash, Carlos Andrés Álvarez Restrepo, Chris Lalancette, Florian Vahltf2_sensor_msgsDisable mem-access warnings on aarch64. (#506)Fix cpplint errors (#497)Reenable sensor_msgs test (#422)Deprecate tf2_sensor_msgs.h (#416)Contributors: Bjar Ne, Chris Lalancette, Jacob Perrontf2_toolsUpdate maintainers to Alejandro Hernandez Cordero and Chris Lalancette (#481)Remove unused import (#465)Adding date-time to frames filename (#454)Use underscores instead of dashes in setup.cfg. (#403)Contributors: Audrow Nash, Hannu Henttinen, Nisala KalupahanatlsfInstall headers to include/${PROJECT_NAME} (#11)Export a modern CMake target instead of old-style variables (#10)Contributors: Shane Loretztlsf_cppInstall includes to include/${PROJECT_NAME} (#114)Export modern CMake targets (#110)Remove the use of malloc hooks from the tlsf_cpp tests. (#109)Contributors: Chris Lalancette, Shane Loretztopic_monitorUpdate maintainers to Audrow Nash and Michael Jeronimo (#543)Small cleanups to the topic monitor. (#517)Fix topic_monitor for high publication rate (#461)Use is_alive for threads. (#510)Contributors: Audrow Nash, Chris Lalancette, Elias De Conincktopic_statistics_demoInstall includes to include/${PROJECT_NAME} (#548)Additional fixes for documentation in demos. (#538)Fixing deprecated subscriber callback warnings (#532)Contributors: Abrar Rahman Protyasha, Chris Lalancette, Shane LoretztracetoolsInstall headers to include/${PROJECT_NAME}Merge branch ‘update-mentions-of-tracetools-test’ into ‘master’ Update applicable mentions of tracetools_test to test_tracetools See merge requestros-tracing/ros2_tracing!259Update applicable mentions of tracetools_test to test_tracetoolsMerge branch ‘version-3-1-0’ into ‘master’ Version 3.1.0 See merge requestros-tracing/ros2_tracing!256Correctly handle calls to TRACEPOINT() macro with no tracepoint argsMove publisher handle tracepoint argument from rclcpp_publish to rcl_publishAdd support for rmw init/pub, take, and executor instrumentationExport target on Windows and export an interface if TRACETOOLS_DISABLEDRemove deprecated utility functionsContributors: Christophe Bedard, Ivan Santiago Paunovic, Shane Loretztracetools_launchDisable kernel tracing by defaultDon’t require kernel tracer and detect when it’s not installedAdd support for preloading pthread and dl instrumentation shared libsRemove profile_fast option and consider LD_PRELOADing both libsImprove event matching for shared lib preloadingImprove LdPreload action’s lib-finding function and add proper testsFix multiple LdPreload actions not working and add testDeprecate ‘context_names’ param and replace with ‘context_fields’Support per-domain context fields for the Trace actionImprove LdPreload.get_shared_lib_path() for when a static lib may existMove some tests from tracetools_launch to test_tracetools_launchExpose Trace action as frontend action and support substitutionsContributors: Christophe Bedard, Ingo Lütkebohletracetools_testAllow providing additional actions for TraceTestCaseRemove default value for ‘package’ kwarg for TraceTestCaseMove actual tests out of tracetools_test to new test_tracetools packageAdd tests for rmw init/pub, take, and executor instrumentationAdd field type assertion utilities to TraceTestCaseFixing deprecated subscriber callback warningsContributors: Abrar Rahman Protyasha, Christophe Bedardtracetools_traceDisable kernel tracing by defaultDon’t require kernel tracer and detect when it’s not installedIntroduce constants for tracepoint namesOptimize default tracing session channel config valuesDeprecate ‘context_names’ param and replace with ‘context_fields’Support per-domain context fields for the Trace actionAdd support for rmw init/pub, take, and executor tracepointsContributors: Christophe Bedardtrajectory_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Contributors: Audrow Nash, GreyturtlesimUsedoublewhen handlingqrealorient\_(#114)Add Rolling Icon (#133)Update maintainers to Audrow Nash and Michael Jeronimo (#137)Fixing deprecated subscriber callback warnings (#134)Use rosidl_get_typesupport_target() (#132)Print out the correct node name on startup. (#122)Contributors: Abrar Rahman Protyasha, Audrow Nash, Chris Lalancette, Katherine Scott, Seulbae Kim, Shane LoretzurdfInstall headers to include/${PROJECT_NAME} (#31)Add linter tests and fix errors (#30)Add in a Doxyfile to predefine macros. (#28)Contributors: Chris Lalancette, Jacob Perron, Shane Loretzurdf_parser_pluginInstall headers to include/${PROJECT_NAME} (#31)Add linter tests and fix errors (#30)Contributors: Jacob Perron, Shane Loretzvisualization_msgsInterface packages should fully on the interface packages that they depend on (#173)Update maintainers to Geoffrey Biggs and Tully Foote (#163)Marker Textures (#153)Document namespace scoped marker deletion. (#151)Contributors: Audrow Nash, Greg Balke, Grey, Michel Hidalgoyaml_cpp_vendorAdd missing dependency on yaml-cpp (#32)Upgrade to yaml-cpp 0.7.0 (#25)Contributors: Chris Lalancette, Scott K Loganzstd_vendorBump version number to avoid conflictUse git hash for zstd vendor (#969)Update package maintainers (#899)Declare missing dependency on ‘git’ in zstd_vendor (#890)Switch to using ‘git apply’ for zstd_vendor patches (#846)Contributors: Chris Lalancette, Christophe Bedard, Michel Hidalgo, Scott K Logan, Shane Loretz \ No newline at end of file diff --git "a/exported_docs/ros2/IDEs_and_Debugging_[community-contributed]\357\203\201.txt" "b/exported_docs/ros2/IDEs_and_Debugging_[community-contributed]\357\203\201.txt" new file mode 100644 index 0000000..f2c08be --- /dev/null +++ "b/exported_docs/ros2/IDEs_and_Debugging_[community-contributed]\357\203\201.txt" @@ -0,0 +1,67 @@ +Title: IDEs and Debugging [community-contributed] +URL: https://docs.ros.org/en/jazzy/How-To-Guides/ROS-2-IDEs.html +Section: Installation +-------------------------------------------------------------------------------- + +IDEs and Debugging [community-contributed]ROS 2 is not made around a specific development environment and the main focus is on building / running from the command line. +Nonetheless Integrated Development Environments (IDEs) can be used to develop, run and/or debug ROS 2 nodes.Below are listed some IDEs and instructions on how to use them with ROS 2.ContentsGeneralInstalled Python CodeVisual Studio CodePythonPyCharmIntegrate for code inspectionAttach to ProcessRun/DebugGeneralInstalled Python CodeBy default, when building workspaces with:colconbuildThe Python code will be coped over into thebuild/installdirectories. +So when attaching a debugger to aros2runcommand from within an IDE, the code being run (from thebuild/install) is not the same as the files opened in the IDE project.There are 2 options to deal with this:Open the source files frombuild/installdirectory and place breakpoints there.Build the workspace with the–symlink-installflag to colcon, which will symlink the source files to thebuild/installdirectory instead.Visual Studio CodeVSCodeis a versatile and free development environment.VSCode is relatively easy to use with ROS 2. +Simply activate your environment in a command line and start the VSCode application from the same terminal and use as normal. +So:Create your ROS workspace as you would normally.In a terminal, source both ROS 2 and your install (if it was built already).Start VSCode from the same command line. The terminal will be blocked until the application is closed again.LinuxmacOSWindowssource/opt/ros/jazzy/setup.bashcd~/dev_wssource./install/setup.bash +/usr/bin/code./src/my_node/. ~/ros2_install/ros2-osx/setup.bashcd ~/dev_ws. ./install/setup.bash/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code ./src/my_node/#ForCMD:call C:\dev\ros2\local_setup.batcd C:\dev_wscall .\install\local_setup.bat"C:\Program Files\Microsoft VS Code\Code.exe" .\src\my_node\#ForPowerShell:C:\dev\ros2\local_setup.ps1cd C:\dev_ws.\install\local_setup.ps1& "C:\Program Files\Microsoft VS Code\Code.exe" .\src\my_node\VSCode and any terminal created inside VSCode will correctly inherit from the parent environment and should have ROS and installed package available.NoteAfter adding packages or making major changes you might need to source your install again. +The simplest way to do this is to close VSCode and restart it as above.PythonIn your workspace, verify the correct interpreter is used. +Through sourcing the basic commandpythonshould be correct, but VSCode likes to resort to an absolute path for Python. +In the bottom right corner click on “Selected Python Interpreter” to change it.If your ROS 2 Python version is from a virtual environment, VSCode will try to source it at each run command. +But we already started VSCode from a sourced environment, so this extra step is not necessary. +You can disable this for the current workspace by finding “Settings” > “Extensions” > “Python” > “Activate Environment” and disabling the check.Now simply run a file or create a configuration inlaunch.json. +Debugging a node is easiest by creating a configuration like apython...command, instead ofros2run/launch.... +An example oflaunch.jsoncould be:{"version":"0.2.0","configurations":[{"name":"Python: File","type":"python","request":"launch","program":"my_node.py"},]}Instead you could also create a configuration for attaching to a running process, under “Attach using Process Id”.SeeSetup ROS 2 with VSCode and Dockerfor full instructions on how to use VSCode, in combination with Docker.PyCharmPyCharmis an IDE specifically for Python.Of course it can only be meaningfully used for nodes made in Python.With PyCharm you can either attach to an existing process (probably started by you viaros2run...orros2launch...) or run the node directly from Python (equivalent topython[file.py].Integrate for code inspectionYou can setup your PyCharm project such that it is fully aware of ROS 2 code, allowing code completion and suggestion.LinuxOpen a terminal, source ROS and start PyCharm:source/opt/ros/humble/setup.bashcdpath/to/dev_ws +/opt/pycharm/bin/pycharm.shAfter selecting the correct interpreter, everything should work.NoteThis is untested.WindowsFirst sourcing ROS and then starting PyCharm from the command line seems to have no effect on Windows. +Instead, some settings need to be tweaked.Create your ROS workspace as you would normally.Start PyCharm normally.Open a project. This should be the root directory of the ROS node you’re developing, e.g.C:\dev_ws\src\my_node.Click “Add new interpreter” > “Add local interpreter…”. +Select a system interpreter (or virtual environment if you’re using one) and select the executable of your ROS Python version (typicallyC:\Python38\python.exe).If you now open one of your code files, you will see warnings about missing imports. +Trying to run the file will confirm these issues.Under the “Python Interpreters” window, find and select your ROS interpreter. +Edit the name to something recognizable. +More importantly, now click the “Show Interpreter Paths” button.In the new window, you will see the paths already associated with this interpreter. +Click the “+” button and add two more paths (according to your ROS install):C:\dev\ros2_humble\binC:\dev\ros2_humble\Lib\site-packagesPyCharm will re-index and when finished it should correctly interpret your project, recognising the ROS 2 system packages. +You can navigate through code, get completion and read doc blurbs as expected.If there are dependencies built alongside with your package, they are probably not yet recognized and result in invalid IDE warnings and runtime errors.Resolve this by:Making sure thePATHoverride in the run/debug configuration includes both the ROS 2 install and your workspace, e.g.:C:\dev\ros2_humble\local_setup.ps1 +C:\dev_ws\install\local_setup.ps1echo$ENV:PathAdding the relevant folders from theinstall/directory to your project sources.Go to “Settings…” and under “Project: “ > “Project Structure” click “Add content root”. +Add all the relevantsite-packagesfolders underinstall/Lib/*.Finally, make sure your run/debug configuration has the option “include content roots in PYTHONPATH” enabled.TipUsing the–merge-installoption with your colcon build will limit the number of depending directories, making it easier to configure PyCharm.Attach to ProcessEven without any configuration to PyCharm, you can always just attach to a running Python node. +Open your project source and simply run your node as usual:ros2runmy_nodemainThen in PyCharm select “Run” > “Attach to Process…”. +It might take a second, but a small window should show listing the currently running Python instances, including your node. +There can be multiple Python processes, so there may be some trial-and-error to find the right one.After selecting an instance, the usual debugging tools are available. +You can pause it or create breakpoints in the code and step through it.NoteThe code in your project might not be the files being executed, seethis.Run/DebugFollow the steps for integration first.Running your Python file from PyCharm will likely result in import errors. +This is because PyCharm extends thePYTHONPATHenvironment variable, but it leavesPATHuntouched. +Necessary library files inros/binare not found.Edit the run/debug configuration for your file and under “Environment Variables:” add a new variable. +It is currently not supported to extend the existingPATH, so we need to override it. +From a sourced ROS terminal, export the content ofPATHwith:echo$Env:PATH. +Copy the result.Back in PyCharm, paste it asPATH, apply changes and run or debug your node. +It should work like any Python project now, allowing easy additions of breakpoints and other debug methods.NoteOn Windows it seems the capitalization of thePATHvariable under “Environment Variables:” must be “path” (all lowercase) in order to work. + +Code Examples: + +Language: unknown +colconbuild + +Language: unknown +source/opt/ros/jazzy/setup.bashcd~/dev_wssource./install/setup.bash +/usr/bin/code./src/my_node/ + +Language: unknown +. ~/ros2_install/ros2-osx/setup.bashcd ~/dev_ws. ./install/setup.bash/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code ./src/my_node/ + +Language: unknown +#ForCMD:call C:\dev\ros2\local_setup.batcd C:\dev_wscall .\install\local_setup.bat"C:\Program Files\Microsoft VS Code\Code.exe" .\src\my_node\#ForPowerShell:C:\dev\ros2\local_setup.ps1cd C:\dev_ws.\install\local_setup.ps1& "C:\Program Files\Microsoft VS Code\Code.exe" .\src\my_node\ + +Language: unknown +{"version":"0.2.0","configurations":[{"name":"Python: File","type":"python","request":"launch","program":"my_node.py"},]} + +Language: unknown +source/opt/ros/humble/setup.bashcdpath/to/dev_ws +/opt/pycharm/bin/pycharm.sh + +Language: unknown +C:\dev\ros2_humble\local_setup.ps1 +C:\dev_ws\install\local_setup.ps1echo$ENV:Path + +Language: unknown +ros2runmy_nodemain diff --git "a/exported_docs/ros2/Implementing_a_custom_memory_allocator\357\203\201.txt" "b/exported_docs/ros2/Implementing_a_custom_memory_allocator\357\203\201.txt" new file mode 100644 index 0000000..f79d40d --- /dev/null +++ "b/exported_docs/ros2/Implementing_a_custom_memory_allocator\357\203\201.txt" @@ -0,0 +1,51 @@ +Title: Implementing a custom memory allocator +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Allocator-Template-Tutorial.html +Section: Installation +-------------------------------------------------------------------------------- + +Implementing a custom memory allocatorGoal:This tutorial will show how to use a custom memory allocator when writing ROS 2 C++ code.Tutorial level:AdvancedTime:20 minutesTable of ContentsBackgroundWriting an allocatorWriting an example mainPassing an allocator to the intra-process pipelineTesting and verifying the codeThe TLSF allocatorThis tutorial will teach you how to integrate a custom allocator for publishers and subscribers so that the default heap allocator is never called while your ROS nodes are executing. +The code for this tutorial is availablehere.BackgroundSuppose you want to write real-time safe code, and you’ve heard about the many dangers of callingnewduring the real-time critical section, because the default heap allocator on most platforms is nondeterministic.By default, many C++ standard library structures will implicitly allocate memory as they grow, such asstd::vector. +However, these data structures also accept an “Allocator” template argument. +If you specify a custom allocator to one of these data structures, it will use that allocator instead of the system allocator to grow or shrink the data structure. +Your custom allocator could have a pool of memory preallocated on the stack, which might be better suited to real-time applications.In the ROS 2 C++ client library (rclcpp), we are following a similar philosophy to the C++ standard library. +Publishers, subscribers, and the Executor accept an Allocator template parameter that controls allocations made by that entity during execution.Writing an allocatorTo write an allocator compatible with ROS 2’s allocator interface, your allocator must be compatible with the C++ standard library allocator interface.Since C++17, the standard library provides something calledstd::pmr::memory_resource. +This is a class that can be derived from to create a custom allocator that fulfills a minimum set of requirements.For example, the following declaration for a custom memory resource fulfills the requirements (of course, you would still need to implement the declared functions in this class):classCustomMemoryResource:publicstd::pmr::memory_resource{private:void*do_allocate(std::size_tbytes,std::size_talignment)override;voiddo_deallocate(void*p,std::size_tbytes,std::size_talignment)override;booldo_is_equal(conststd::pmr::memory_resource&other)constnoexceptoverride;};To learn about the full capabilities ofstd::pmr::memory_resource, seehttps://en.cppreference.com/w/cpp/memory/memory_resource.The full implementation of the custom allocator for this tutorial is inhttps://github.com/ros2/demos/blob/jazzy/demo_nodes_cpp/src/topics/allocator_tutorial_pmr.cpp.Writing an example mainOnce you have written a valid C++ allocator, you must pass it as a shared pointer to your publisher, subscriber, and executor. +But first, we’ll declare a few aliases to shorten the names.usingrclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy;usingAlloc=std::pmr::polymorphic_allocator;usingMessageAllocTraits=rclcpp::allocator::AllocRebind;usingMessageAlloc=MessageAllocTraits::allocator_type;usingMessageDeleter=rclcpp::allocator::Deleter;usingMessageUniquePtr=std::unique_ptr;Now we can create our resources with the custom allocator:CustomMemoryResourcemem_resource{};autoalloc=std::make_shared(&mem_resource);rclcpp::PublisherOptionsWithAllocatorpublisher_options;publisher_options.allocator=alloc;autopublisher=node->create_publisher("allocator_tutorial",10,publisher_options);rclcpp::SubscriptionOptionsWithAllocatorsubscription_options;subscription_options.allocator=alloc;automsg_mem_strat=std::make_shared>(alloc);autosubscriber=node->create_subscription("allocator_tutorial",10,callback,subscription_options,msg_mem_strat);std::shared_ptrmemory_strategy=std::make_shared>(alloc);rclcpp::ExecutorOptionsoptions;options.memory_strategy=memory_strategy;rclcpp::executors::SingleThreadedExecutorexecutor(options);You must also instantiate a custom deleter and allocator for use when allocating messages:MessageDeletermessage_deleter;MessageAllocmessage_alloc=*alloc;rclcpp::allocator::set_allocator_for_deleter(&message_deleter,&message_alloc);Once you’ve add the node to the executor, it is time to spin. +We’ll use the custom allocator to allocate each message:uint32_ti=0;while(rclcpp::ok()){autoptr=MessageAllocTraits::allocate(message_alloc,1);MessageAllocTraits::construct(message_alloc,ptr);MessageUniquePtrmsg(ptr,message_deleter);msg->data=i;++i;publisher->publish(std::move(msg));rclcpp::sleep_for(10ms);executor.spin_some();}Passing an allocator to the intra-process pipelineEven though we instantiated a publisher and subscriber in the same process, we aren’t using the intra-process pipeline yet.The IntraProcessManager is a class that is usually hidden from the user, but in order to pass a custom allocator to it we need to expose it by getting it from the rclcpp Context. +The IntraProcessManager makes use of several standard library structures, so without a custom allocator it will call the defaultnew.autocontext=rclcpp::contexts::get_global_default_context();autooptions=rclcpp::NodeOptions().context(context).use_intra_process_comms(true);autonode=rclcpp::Node::make_shared("allocator_example",options);Make sure to instantiate publishers and subscribers AFTER constructing the node in this way.Testing and verifying the codeHow do you know that your custom allocator is actually getting called?The obvious thing to do would be to count the calls made to your custom allocator’sallocateanddeallocatefunctions and compare that to the calls tonewanddelete.Adding counting to the custom allocator is easy:void*do_allocate(std::size_tsize,std::size_talignment)override{// ...num_allocs++;// ...}voiddo_deallocate(void*p,std::size_tbytes,std::size_talignment)override{// ...num_deallocs++;// ...}You can also override the globalnewanddeleteoperators:void*operatornew(std::size_tsize){if(is_running){global_runtime_allocs++;}returnstd::malloc(size);}voidoperatordelete(void*ptr,size_t)noexcept{if(ptr!=nullptr){if(is_running){global_runtime_deallocs++;}std::free(ptr);}}voidoperatordelete(void*ptr)noexcept{if(ptr!=nullptr){if(is_running){global_runtime_deallocs++;}std::free(ptr);}}where the variables we are incrementing are just global static integers, andis_runningis a global static boolean that gets toggled right before the call tospin.Theexample executableprints the value of the variables. +To run the example executable, use:ros2 run demo_nodes_cpp allocator_tutorialor, to run the example with the intra-process pipeline on:ros2 run demo_nodes_cpp allocator_tutorial intraYou should get numbers like:Global new was called 15590 times during spinGlobal delete was called 15590 times during spinAllocator new was called 27284 times during spinAllocator delete was called 27281 times during spinWe’ve caught about 2/3 of the allocations/deallocations that happen on the execution path, but where do the remaining 1/3 come from?As a matter of fact, these allocations/deallocations originate in the underlying DDS implementation used in this example.Proving this is out of the scope of this tutorial, but you can check out the test for the allocation path that gets run as part of the ROS 2 continuous integration testing, which backtraces through the code and figures out whether certain function calls originate in the rmw implementation or in a DDS implementation:https://github.com/ros2/realtime_support/blob/jazzy/tlsf_cpp/test/test_tlsf.cpp#L41Note that this test is not using the custom allocator we just created, but the TLSF allocator (see below).The TLSF allocatorROS 2 offers support for the TLSF (Two Level Segregate Fit) allocator, which was designed to meet real-time requirements:https://github.com/ros2/realtime_support/tree/jazzy/tlsf_cppFor more information about TLSF, seehttp://www.gii.upv.es/tlsf/Note that the TLSF allocator is licensed under a dual-GPL/LGPL license.A full working example using the TLSF allocator is here:https://github.com/ros2/realtime_support/blob/jazzy/tlsf_cpp/example/allocator_example.cpp + +Code Examples: + +Language: unknown +classCustomMemoryResource:publicstd::pmr::memory_resource{private:void*do_allocate(std::size_tbytes,std::size_talignment)override;voiddo_deallocate(void*p,std::size_tbytes,std::size_talignment)override;booldo_is_equal(conststd::pmr::memory_resource&other)constnoexceptoverride;}; + +Language: unknown +usingrclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy;usingAlloc=std::pmr::polymorphic_allocator;usingMessageAllocTraits=rclcpp::allocator::AllocRebind;usingMessageAlloc=MessageAllocTraits::allocator_type;usingMessageDeleter=rclcpp::allocator::Deleter;usingMessageUniquePtr=std::unique_ptr; + +Language: unknown +CustomMemoryResourcemem_resource{};autoalloc=std::make_shared(&mem_resource);rclcpp::PublisherOptionsWithAllocatorpublisher_options;publisher_options.allocator=alloc;autopublisher=node->create_publisher("allocator_tutorial",10,publisher_options);rclcpp::SubscriptionOptionsWithAllocatorsubscription_options;subscription_options.allocator=alloc;automsg_mem_strat=std::make_shared>(alloc);autosubscriber=node->create_subscription("allocator_tutorial",10,callback,subscription_options,msg_mem_strat);std::shared_ptrmemory_strategy=std::make_shared>(alloc);rclcpp::ExecutorOptionsoptions;options.memory_strategy=memory_strategy;rclcpp::executors::SingleThreadedExecutorexecutor(options); + +Language: unknown +MessageDeletermessage_deleter;MessageAllocmessage_alloc=*alloc;rclcpp::allocator::set_allocator_for_deleter(&message_deleter,&message_alloc); + +Language: unknown +uint32_ti=0;while(rclcpp::ok()){autoptr=MessageAllocTraits::allocate(message_alloc,1);MessageAllocTraits::construct(message_alloc,ptr);MessageUniquePtrmsg(ptr,message_deleter);msg->data=i;++i;publisher->publish(std::move(msg));rclcpp::sleep_for(10ms);executor.spin_some();} + +Language: unknown +autocontext=rclcpp::contexts::get_global_default_context();autooptions=rclcpp::NodeOptions().context(context).use_intra_process_comms(true);autonode=rclcpp::Node::make_shared("allocator_example",options); + +Language: unknown +void*do_allocate(std::size_tsize,std::size_talignment)override{// ...num_allocs++;// ...}voiddo_deallocate(void*p,std::size_tbytes,std::size_talignment)override{// ...num_deallocs++;// ...} + +Language: unknown +void*operatornew(std::size_tsize){if(is_running){global_runtime_allocs++;}returnstd::malloc(size);}voidoperatordelete(void*ptr,size_t)noexcept{if(ptr!=nullptr){if(is_running){global_runtime_deallocs++;}std::free(ptr);}}voidoperatordelete(void*ptr)noexcept{if(ptr!=nullptr){if(is_running){global_runtime_deallocs++;}std::free(ptr);}} + +Language: unknown +ros2 run demo_nodes_cpp allocator_tutorial + +Language: unknown +ros2 run demo_nodes_cpp allocator_tutorial intra + +Language: unknown +Global new was called 15590 times during spinGlobal delete was called 15590 times during spinAllocator new was called 27284 times during spinAllocator delete was called 27281 times during spin diff --git "a/exported_docs/ros2/Implementing_custom_interfaces\357\203\201.txt" "b/exported_docs/ros2/Implementing_custom_interfaces\357\203\201.txt" new file mode 100644 index 0000000..2737cb3 --- /dev/null +++ "b/exported_docs/ros2/Implementing_custom_interfaces\357\203\201.txt" @@ -0,0 +1,116 @@ +Title: Implementing custom interfaces +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Single-Package-Define-And-Use-Interface.html +Section: Installation +-------------------------------------------------------------------------------- + +Implementing custom interfacesGoal:Learn more ways to implement custom interfaces in ROS 2.Tutorial level:BeginnerTime:15 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Create a msg file3 Use an interface from the same package4 Try it out5 (Extra) Use an existing interface definitionSummaryNext stepsRelated contentBackgroundIn aprevious tutorial, you learned how to create custom msg and srv interfaces.While best practice is to declare interfaces in dedicated interface packages, sometimes it can be convenient to declare, create and use an interface all in one package.Recall that interfaces can currently only be defined in CMake packages. +It is possible, however, to have Python libraries and nodes in CMake packages (usingament_cmake_python), so you could define interfaces and Python nodes together in one package. +We’ll use a CMake package and C++ nodes here for the sake of simplicity.This tutorial will focus on the msg interface type, but the steps here are applicable to all interface types.PrerequisitesWe assume you’ve reviewed the basics in theCreating custom msg and srv filestutorial before working through this one.You should haveROS 2 installed, aworkspace, and an understanding ofcreating packages.As always, don’t forget tosource ROS 2in every new terminal you open.Tasks1 Create a packageIn your workspacesrcdirectory, create a packagemore_interfacesand make a directory within it for msg files:ros2 pkg create --build-type ament_cmake --license Apache-2.0 more_interfacesmkdir more_interfaces/msg2 Create a msg fileInsidemore_interfaces/msg, create a new fileAddressBook.msg, and paste the following code to create a message meant to carry information about an individual:uint8PHONE_TYPE_HOME=0uint8PHONE_TYPE_WORK=1uint8PHONE_TYPE_MOBILE=2stringfirst_namestringlast_namestringphone_numberuint8phone_typeThis message is composed of these fields:first_name: of type stringlast_name: of type stringphone_number: of type stringphone_type: of type uint8, with several named constant values definedNote that it’s possible to set default values for fields within a message definition. +SeeInterfacesfor more ways you can customize interfaces.Next, we need to make sure that the msg file is turned into source code for C++, Python, and other languages.2.1 Build a msg fileOpenpackage.xmland add the following lines:rosidl_default_generatorsrosidl_default_runtimerosidl_interface_packagesNote that at build time, we needrosidl_default_generators, while at runtime, we only needrosidl_default_runtime.OpenCMakeLists.txtand add the following lines:Find the package that generates message code from msg/srv files:find_package(rosidl_default_generatorsREQUIRED)Declare the list of messages you want to generate:set(msg_files"msg/AddressBook.msg")By adding the .msg files manually, we make sure that CMake knows when it has to reconfigure the project after you add other .msg files.Generate the messages:rosidl_generate_interfaces(${PROJECT_NAME}${msg_files})Also make sure you export the message runtime dependency:ament_export_dependencies(rosidl_default_runtime)Now you’re ready to generate source files from your msg definition. +We’ll skip the compile step for now as we’ll do it all together below in step 4.3 Use an interface from the same packageNow we can start writing code that uses this message.Inmore_interfaces/srccreate a file calledpublish_address_book.cppand paste the following code:#include#include#include"rclcpp/rclcpp.hpp"#include"more_interfaces/msg/address_book.hpp"usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this->create_publisher("address_book",10);autopublish_msg=[this]()->void{automessage=more_interfaces::msg::AddressBook();message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;std::cout<<"Publishing Contact\nFirst:"<address_book_publisher_->publish(message);};timer_=this->create_wall_timer(1s,publish_msg);}private:rclcpp::Publisher::SharedPtraddress_book_publisher_;rclcpp::TimerBase::SharedPtrtimer_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}3.1 The code explainedInclude the header of our newly createdAddressBook.msg.#include"more_interfaces/msg/address_book.hpp"Create a node and anAddressBookpublisher.usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this->create_publisher("address_book");Create a callback to publish the messages periodically.autopublish_msg=[this]()->void{Create anAddressBookmessage instance that we will later publish.automessage=more_interfaces::msg::AddressBook();PopulateAddressBookfields.message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;Finally send the message periodically.std::cout<<"Publishing Contact\nFirst:"<address_book_publisher_->publish(message);Create a 1 second timer to call ourpublish_msgfunction every second.timer_=this->create_wall_timer(1s,publish_msg);3.2 Build the publisherWe need to create a new target for this node in theCMakeLists.txt:find_package(rclcppREQUIRED)add_executable(publish_address_booksrc/publish_address_book.cpp)ament_target_dependencies(publish_address_bookrclcpp)install(TARGETSpublish_address_bookDESTINATIONlib/${PROJECT_NAME})3.3 Link against the interfaceIn order to use the messages generated in the same package we need to use the following CMake code:rosidl_get_typesupport_target(cpp_typesupport_target${PROJECT_NAME}rosidl_typesupport_cpp)target_link_libraries(publish_address_book"${cpp_typesupport_target}")This finds the relevant generated C++ code fromAddressBook.msgand allows your target to link against it.You may have noticed that this step was not necessary when the interfaces being used were from a different package that was built independently. +This CMake code is only required when you want to use interfaces in the same package as the one in which they are defined.4 Try it outReturn to the root of the workspace to build the package:LinuxmacOSWindowscd ~/ros2_wscolcon build --packages-up-to more_interfacescd ~/ros2_wscolcon build --packages-up-to more_interfacescd /ros2_wscolcon build --merge-install --packages-up-to more_interfacesThen source the workspace and run the publisher:LinuxmacOSWindowssource install/local_setup.bashros2 run more_interfaces publish_address_book. install/local_setup.bashros2 run more_interfaces publish_address_bookcall install/local_setup.batros2 run more_interfaces publish_address_bookOr using Powershell:install/local_setup.ps1ros2 run more_interfaces publish_address_bookYou should see the publisher relaying the msg you defined, including the values you set inpublish_address_book.cpp.To confirm the message is being published on theaddress_booktopic, open another terminal, source the workspace, and calltopicecho:LinuxmacOSWindowssource install/setup.bashros2 topic echo /address_book. install/setup.bashros2 topic echo /address_bookcall install/setup.batros2 topic echo /address_bookOr using Powershell:install/setup.ps1ros2 topic echo /address_bookWe won’t create a subscriber in this tutorial, but you can try to write one yourself for practice (useWriting a simple publisher and subscriber (C++)to help).5 (Extra) Use an existing interface definitionNoteYou can use an existing interface definition in a new interface definition. +For example, let’s say there is a message namedContact.msgthat belongs to an existing ROS 2 package namedrosidl_tutorials_msgs. +Assume that its definition is identical to our custom-madeAddressBook.msginterface from earlier.In that case you could have definedAddressBook.msg(an interface in the packagewithyour nodes) as typeContact(an interface in aseparatepackage). +You could even defineAddressBook.msgas anarrayof typeContact, like so:rosidl_tutorials_msgs/Contact[]address_bookTo generate this message you would need to declare a dependency onContact.msg'spackage,rosidl_tutorials_msgs, inpackage.xml:rosidl_tutorials_msgsrosidl_tutorials_msgsAnd inCMakeLists.txt:find_package(rosidl_tutorials_msgsREQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}${msg_files}DEPENDENCIESrosidl_tutorials_msgs)You would also need to include the header ofContact.msgin your publisher node in order to be able to addcontactsto youraddress_book.#include"rosidl_tutorials_msgs/msg/contact.hpp"You could change the callback to something like this:autopublish_msg=[this]()->void{automsg=std::make_shared();{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="John";contact.last_name="Doe";contact.phone_number="1234567890";contact.phone_type=message.PHONE_TYPE_MOBILE;msg->address_book.push_back(contact);}{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="Jane";contact.last_name="Doe";contact.phone_number="4254242424";contact.phone_type=message.PHONE_TYPE_HOME;msg->address_book.push_back(contact);}std::cout<<"Publishing address book:"<address_book){std::cout<<"First:"<publish(*msg);};Building and running these changes would show the msg defined as expected, as well as the array of msgs defined above.SummaryIn this tutorial, you tried out different field types for defining interfaces, then built an interface in the same package where it’s being used.You also learned how to use another interface as a field type, as well as thepackage.xml,CMakeLists.txt, and#includestatements necessary for utilizing that feature.Next stepsNext you will create a simple ROS 2 package with a custom parameter that you will learn to set from a launch file. +Again, you can choose to write it in eitherC++orPython.Related contentThere areseveral design articleson ROS 2 interfaces and the IDL (interface definition language). + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 more_interfacesmkdir more_interfaces/msg + +Language: unknown +uint8PHONE_TYPE_HOME=0uint8PHONE_TYPE_WORK=1uint8PHONE_TYPE_MOBILE=2stringfirst_namestringlast_namestringphone_numberuint8phone_type + +Language: unknown +rosidl_default_generatorsrosidl_default_runtimerosidl_interface_packages + +Language: unknown +find_package(rosidl_default_generatorsREQUIRED) + +Language: unknown +set(msg_files"msg/AddressBook.msg") + +Language: unknown +rosidl_generate_interfaces(${PROJECT_NAME}${msg_files}) + +Language: unknown +ament_export_dependencies(rosidl_default_runtime) + +Language: unknown +#include#include#include"rclcpp/rclcpp.hpp"#include"more_interfaces/msg/address_book.hpp"usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this->create_publisher("address_book",10);autopublish_msg=[this]()->void{automessage=more_interfaces::msg::AddressBook();message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE;std::cout<<"Publishing Contact\nFirst:"<address_book_publisher_->publish(message);};timer_=this->create_wall_timer(1s,publish_msg);}private:rclcpp::Publisher::SharedPtraddress_book_publisher_;rclcpp::TimerBase::SharedPtrtimer_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +#include"more_interfaces/msg/address_book.hpp" + +Language: unknown +usingnamespacestd::chrono_literals;classAddressBookPublisher:publicrclcpp::Node{public:AddressBookPublisher():Node("address_book_publisher"){address_book_publisher_=this->create_publisher("address_book"); + +Language: unknown +autopublish_msg=[this]()->void{ + +Language: unknown +automessage=more_interfaces::msg::AddressBook(); + +Language: unknown +message.first_name="John";message.last_name="Doe";message.phone_number="1234567890";message.phone_type=message.PHONE_TYPE_MOBILE; + +Language: unknown +std::cout<<"Publishing Contact\nFirst:"<address_book_publisher_->publish(message); + +Language: unknown +timer_=this->create_wall_timer(1s,publish_msg); + +Language: unknown +find_package(rclcppREQUIRED)add_executable(publish_address_booksrc/publish_address_book.cpp)ament_target_dependencies(publish_address_bookrclcpp)install(TARGETSpublish_address_bookDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +rosidl_get_typesupport_target(cpp_typesupport_target${PROJECT_NAME}rosidl_typesupport_cpp)target_link_libraries(publish_address_book"${cpp_typesupport_target}") + +Language: unknown +cd ~/ros2_wscolcon build --packages-up-to more_interfaces + +Language: unknown +cd ~/ros2_wscolcon build --packages-up-to more_interfaces + +Language: unknown +cd /ros2_wscolcon build --merge-install --packages-up-to more_interfaces + +Language: unknown +source install/local_setup.bashros2 run more_interfaces publish_address_book + +Language: unknown +. install/local_setup.bashros2 run more_interfaces publish_address_book + +Language: unknown +call install/local_setup.batros2 run more_interfaces publish_address_book + +Language: unknown +install/local_setup.ps1ros2 run more_interfaces publish_address_book + +Language: unknown +source install/setup.bashros2 topic echo /address_book + +Language: unknown +. install/setup.bashros2 topic echo /address_book + +Language: unknown +call install/setup.batros2 topic echo /address_book + +Language: unknown +install/setup.ps1ros2 topic echo /address_book + +Language: unknown +rosidl_tutorials_msgs/Contact[]address_book + +Language: unknown +rosidl_tutorials_msgsrosidl_tutorials_msgs + +Language: unknown +find_package(rosidl_tutorials_msgsREQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}${msg_files}DEPENDENCIESrosidl_tutorials_msgs) + +Language: unknown +#include"rosidl_tutorials_msgs/msg/contact.hpp" + +Language: unknown +autopublish_msg=[this]()->void{automsg=std::make_shared();{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="John";contact.last_name="Doe";contact.phone_number="1234567890";contact.phone_type=message.PHONE_TYPE_MOBILE;msg->address_book.push_back(contact);}{rosidl_tutorials_msgs::msg::Contactcontact;contact.first_name="Jane";contact.last_name="Doe";contact.phone_number="4254242424";contact.phone_type=message.PHONE_TYPE_HOME;msg->address_book.push_back(contact);}std::cout<<"Publishing address book:"<address_book){std::cout<<"First:"<publish(*msg);}; diff --git a/exported_docs/ros2/Installation.txt b/exported_docs/ros2/Installation.txt new file mode 100644 index 0000000..0ba65d4 --- /dev/null +++ b/exported_docs/ros2/Installation.txt @@ -0,0 +1,5 @@ +Title: Installation +URL: https://docs.ros.org/en/jazzy/Installation.html +Section: Installation +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/ros2/Installation_(Ubuntu)\357\203\201.txt" "b/exported_docs/ros2/Installation_(Ubuntu)\357\203\201.txt" new file mode 100644 index 0000000..c269ce3 --- /dev/null +++ "b/exported_docs/ros2/Installation_(Ubuntu)\357\203\201.txt" @@ -0,0 +1,48 @@ +Title: Installation (Ubuntu) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Installation-Ubuntu.html +Section: Installation +-------------------------------------------------------------------------------- + +Installation (Ubuntu)Goal:Install thewebots_ros2package and run simulation examples on Ubuntu.Tutorial level:AdvancedTime:10 minutesContentsBackgroundPrerequisitesMultiple Installations of WebotsTasks1 Installwebots_ros22 Launch thewebots_ros2_universal_robotexampleBackgroundThewebots_ros2package provides an interface between ROS 2 and Webots. +It includes several sub-packages, includingwebots_ros2_driver, which allows you to start Webots and communicate with it. +This interface is used in most of the following tutorials, so it is required to install it beforehand. +Other sub-packages are mainly examples that show multiple possible implementations using the interface. +In this tutorial, you are going to install the package and learn how to run one of these examples.PrerequisitesIt is recommended to understand basic ROS principles covered in the beginnerTutorials. +In particular,Creating a workspaceandCreating a packageare useful prerequisites.The Webots software should be installed in order to use thewebots_ros2interface. +You can follow theinstallation procedureorbuild it from sources.Alternatively, you can also letwebots_ros2download and install Webots automatically. +This option appears when you launch an example of the package and no Webots installation is found.Multiple Installations of WebotsIf you have installed different versions of Webots on your computer,webots_ros2will look for Webots at the following locations (in this order):If theROS2_WEBOTS_HOMEenvironment variable is set, ROS 2 will use the Webots in this folder, regardless of its version.If theWEBOTS_HOMEenvironment variable is set, ROS 2 will use the Webots in this folder, regardless of its version.If none of these variables is set,webots_ros2will look for Webots in the default installation paths for a compatible version:/usr/local/webotsand/snap/webots/current/usr/share/webots.If Webots couldn’t be found,webots_ros2will show a window offering the automatic installation of the latest compatible version of Webots.Tasks1 Installwebots_ros2You can either install the official released package, or install it from the latest up-to-date sources fromGithub.Installwebots_ros2distributed packageInstallwebots_ros2from sourcesRun the following command in a terminal.sudo apt-get install ros-jazzy-webots-ros2Create a ROS 2 workspace with itssrcdirectory.mkdir -p ~/ros2_ws/srcSource the ROS 2 environment.source /opt/ros/jazzy/setup.bashRetrieve the sources from Github.cd ~/ros2_wsgit clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2Install the package dependencies.sudo apt install python3-pip python3-rosdep python3-colcon-common-extensionssudo rosdep init && rosdep updaterosdep install --from-paths src --ignore-src --rosdistro jazzyBuild the package usingcolcon.colcon buildSource this workspace.source install/local_setup.bash2 Launch thewebots_ros2_universal_robotexampleThe following instructions explain how to start a provided example.First source the ROS 2 environment, if not done already.source /opt/ros/jazzy/setup.bashSetting theWEBOTS_HOMEenvironment variable allows you to start a specific Webots installation.export WEBOTS_HOME=/usr/local/webotsIf installed from sources, source your ROS 2 workspace, if not done already.cd ~/ros2_wssource install/local_setup.bashUse the ROS 2 launch command to start demo packages (e.g.webots_ros2_universal_robot).ros2 launch webots_ros2_universal_robot multirobot_launch.py + +Code Examples: + +Language: unknown +sudo apt-get install ros-jazzy-webots-ros2 + +Language: unknown +mkdir -p ~/ros2_ws/src + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +cd ~/ros2_wsgit clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2 + +Language: unknown +sudo apt install python3-pip python3-rosdep python3-colcon-common-extensionssudo rosdep init && rosdep updaterosdep install --from-paths src --ignore-src --rosdistro jazzy + +Language: unknown +colcon build + +Language: unknown +source install/local_setup.bash + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +export WEBOTS_HOME=/usr/local/webots + +Language: unknown +cd ~/ros2_wssource install/local_setup.bash + +Language: unknown +ros2 launch webots_ros2_universal_robot multirobot_launch.py diff --git "a/exported_docs/ros2/Installation_(Windows)\357\203\201.txt" "b/exported_docs/ros2/Installation_(Windows)\357\203\201.txt" new file mode 100644 index 0000000..0aa2b3f --- /dev/null +++ "b/exported_docs/ros2/Installation_(Windows)\357\203\201.txt" @@ -0,0 +1,66 @@ +Title: Installation (Windows) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Installation-Windows.html +Section: Installation +-------------------------------------------------------------------------------- + +Installation (Windows)Goal:Install thewebots_ros2package and run simulation examples on Windows.Tutorial level:AdvancedTime:10 minutesContentsBackgroundPrerequisitesMultiple Installations of WebotsTasks1 Install WSL22 Install ROS 2 in WSL3 Installwebots_ros24 Launch thewebots_ros2_universal_robotexample5 RViz troubleshootingBackgroundThewebots_ros2package provides an interface between ROS 2 and Webots. +It includes several sub-packages, includingwebots_ros2_driver, which allows ROS nodes to communicate with Webots. +Other sub-packages are mainly examples that show multiple possible implementations using the interface. +In this tutorial, you are going to install the package and learn how to run one of these examples.PrerequisitesIt is recommended to understand basic ROS principles covered in the beginnerTutorials. +In particular,Creating a workspaceandCreating a packageare useful prerequisites.Webots is a prerequisite to use thewebots_ros2package. +You can follow theinstallation procedureorbuild it from sources.Alternatively, you can also letwebots_ros2download Webots automatically. +This option appears when you launch an example of the package and no Webots installation is found.Multiple Installations of WebotsIf you have more than one installation of Webots, ROS 2 will look for Webots at the following locations (in this order):If theROS2_WEBOTS_HOMEenvironment variable is set, ROS 2 will use the Webots in this folder, regardless of its version.If theWEBOTS_HOMEenvironment variable is set, ROS 2 will use the Webots in this folder, regardless of its version.If none of the previous points is set/installed ROS 2 will look for Webots in the default installation paths for a compatible version:C:\ProgramFiles\Webots.If Webots couldn’t be found,webots_ros2will show a window and offer automatic Webots installation of the last compatible version.Tasks1 Install WSL2On Windows, WSL (Windows Subsystem for Linux) improves the user experience with ROS 2 compared to native Windows installation, as it runs on a Linux platform. +Install WSL with an Ubuntu version which is compatible with your ROS distribution and upgrade to WSL2 following theofficial Microsoft tutorial.2 Install ROS 2 in WSLInstall ROS 2 inside Ubuntu WSL, followingUbuntu (deb packages).3 Installwebots_ros2You can then either installwebots_ros2from the official released package, or install it from the latest up-to-date sources fromGithub.The following commands must be run inside the WSL environment.Installwebots_ros2distributed packageInstallwebots_ros2from sourcesRun the following command in a terminal.sudo apt-get install ros-jazzy-webots-ros2Create a ROS 2 workspace with itssrcdirectory.mkdir -p ~/ros2_ws/srcSource the ROS 2 environment.source /opt/ros/jazzy/setup.bashRetrieve the sources from Github.cd ~/ros2_wsgit clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2Install the package dependencies.sudo apt install python3-pip python3-rosdep python3-colcon-common-extensionssudo rosdep init && rosdep updaterosdep install --from-paths src --ignore-src --rosdistro jazzyBuild the package usingcolcon.colcon buildSource this workspace.source install/local_setup.bash4 Launch thewebots_ros2_universal_robotexampleWSL doesn’t support hardware acceleration (yet). +Therefore, Webots should be started on Windows, while the ROS part is running inside WSL. +To do so, the following commands must be run inside the WSL environment.First source the ROS 2 environment, if not done already.source /opt/ros/jazzy/setup.bashSetting theWEBOTS_HOMEenvironment variable allows you to start a specific Webots installation (e.g.C:\ProgramFiles\Webots). +Use the mount point “/mnt” to refer to a path on native Windows.export WEBOTS_HOME=/mnt/c/Program\ Files/WebotsIf installed from sources, source your ROS 2 workspace, if not done already.cd ~/ros2_wssource install/local_setup.bashUse the ROS 2 launch command to start demo packages (e.g.webots_ros2_universal_robot).ros2 launch webots_ros2_universal_robot multirobot_launch.py5 RViz troubleshootingWith recent versions of WSL2, RViz should work out of the box.You can check if it works correctly by running any example that uses RViz, for example:sudo apt install ros-jazzy-slam-toolboxros2 launch webots_ros2_tiago robot_launch.py rviz:=true slam:=trueThe Tiago robot can be controlled using:ros2 run teleop_twist_keyboard teleop_twist_keyboardWith older WSL versions, RViz2 may not work directly, as no display is available. To use RViz, you can either upgrade WSL or enable X11 forwarding.Upgrade WSLEnable X11 forwardingIn a Windows shell:wsl --updateFor older versions of WSL, the following steps can be followed:InstallVcXsrv.Launch VcXsrv. You can leave most of the parameters default, except theExtrasettingspage, where you must setClipboard,PrimarySelectionandDisableaccesscontroland unsetNativeopengl.You can save the configuration for future launches.Click onFinish, you will see that the X11 server is running in the icon tray.In your WSL environment, export theDISPLAYvariable.export DISPLAY=$(ip route list default | awk '{print }'):0You can add this to your.bashrc, so that it is set for every future WSL environment.echo "export DISPLAY=$(ip route list default | awk '{print }'):0" >> ~/.bashrc + +Code Examples: + +Language: unknown +sudo apt-get install ros-jazzy-webots-ros2 + +Language: unknown +mkdir -p ~/ros2_ws/src + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +cd ~/ros2_wsgit clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2 + +Language: unknown +sudo apt install python3-pip python3-rosdep python3-colcon-common-extensionssudo rosdep init && rosdep updaterosdep install --from-paths src --ignore-src --rosdistro jazzy + +Language: unknown +colcon build + +Language: unknown +source install/local_setup.bash + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +export WEBOTS_HOME=/mnt/c/Program\ Files/Webots + +Language: unknown +cd ~/ros2_wssource install/local_setup.bash + +Language: unknown +ros2 launch webots_ros2_universal_robot multirobot_launch.py + +Language: unknown +sudo apt install ros-jazzy-slam-toolboxros2 launch webots_ros2_tiago robot_launch.py rviz:=true slam:=true + +Language: unknown +ros2 run teleop_twist_keyboard teleop_twist_keyboard + +Language: unknown +wsl --update + +Language: unknown +export DISPLAY=$(ip route list default | awk '{print }'):0 + +Language: unknown +echo "export DISPLAY=$(ip route list default | awk '{print }'):0" >> ~/.bashrc diff --git "a/exported_docs/ros2/Installation_(macOS)\357\203\201.txt" "b/exported_docs/ros2/Installation_(macOS)\357\203\201.txt" new file mode 100644 index 0000000..17e7555 --- /dev/null +++ "b/exported_docs/ros2/Installation_(macOS)\357\203\201.txt" @@ -0,0 +1,82 @@ +Title: Installation (macOS) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Installation-MacOS.html +Section: Installation +-------------------------------------------------------------------------------- + +Installation (macOS)Goal:Install thewebots_ros2package and run simulation examples on macOS.Tutorial level:AdvancedTime:10 minutesContentsBackgroundPrerequisitesTasks1 Create the VM image2 Configure the VM3 Installwebots_ros24 Launch thewebots_ros2_universal_robotexampleBackgroundThewebots_ros2package provides an interface between ROS 2 and Webots. +It includes several sub-packages, includingwebots_ros2_driver, which allows you to start Webots and communicate with it. +Other sub-packages are mainly examples that show multiple possible implementations using the interface. +In this tutorial, you are going to install the package and learn how to run one of these examples.PrerequisitesIt is recommended to understand basic ROS principles covered in the beginnerTutorials. +In particular,Creating a workspaceandCreating a packageare useful prerequisites.It is necessary to install Webots natively on the mac in order to use thewebots_ros2package in the virtual machine as explained below. +You can follow theinstallation procedureorbuild it from sources.TasksOn macOS, a solution based on UTM virtual machines provides an improved user experience with ROS 2 compared to native macOS installation, as it runs ROS in a Linux environment. +However, Webots should be installed natively on macOS and it will be able to communicate with the ROS nodes running in the Virtual Machine (VM). +This solution allows for native 3D hardware acceleration for Webots. +The VM runs all the ROS part (including RViz) and connects to the host machine through TCP to start Webots. +A shared folder allows the script to transfer the world and other resource files from the VM to macOS where Webots is running.The following steps explain how to create the VM image with the installation of thewebots_ros2released package. +It is also possible to install it from sources.1 Create the VM imageInstall UTM on your macOS machine. +The link can be found on theofficial UTM website.Download the .iso image ofUbuntu 22.04for Humble and Rolling orUbuntu 20.04for Foxy. +Be sure to download the image corresponding to your CPU architecture.In the UTM software:Create a new image and chooseVirtualizeoption.Select the ISO image you have downloaded in theBootISOImagefield.Leave all hardware settings at default (including hardware acceleration disabled).In theSharedDirectorywindow, select a folder that will be used bywebots_ros2to transfer all the Webots assets to the host. +In this example, the selected folder is/Users/username/shared.Leave all the remaining parameters as default.Start the VM. +Note that you can select another shared folder each time you start the VM.During the first launch of the VM, install Ubuntu and choose a username for your account. In this example, the username isubuntu.Once Ubuntu is installed, close the VM, remove the iso image from the CD/DVD field and restart the VM.2 Configure the VMIn this section, ROS 2 is installed in the VM and the shared folder is configured. +The following instructions and commands are all run inside the VM.Open a terminal in the started VM and install the ROS 2 distribution you need by following the instructions inUbuntu (deb packages):Create a folder in the VM to use as a shared folder. +In this example, the shared folder in the VM is/home/ubuntu/shared.mkdir /home/ubuntu/sharedTo mount this folder to the host, execute the following command. +Don’t forget to modify the path to the shared folder, if it is different in your case.sudo mount -t 9p -o trans=virtio share /home/ubuntu/shared -oversion=9p2000.LTo automatically mount this folder to the host when starting the VM, add the following line to/etc/fstab. +Don’t forget to modify the path to the shared folder, if it is different in your case.share /home/ubuntu/shared 9p trans=virtio,version=9p2000.L,rw,_netdev,nofail 0 0The environment variableWEBOTS_SHARED_FOLDERmust always be set in order for the package to work properly in the VM. +This variable specifies the location of the shared folder that is used to exchange data between the host machine and the virtual machine (VM) to thewebots_ros2package. +The value to use for this variable should be in the format of:, whereis the path to the shared folder on the host machine andis the path to the same shared folder on the VM.In this example:export WEBOTS_SHARED_FOLDER=/Users/username/shared:/home/ubuntu/sharedYou can add this command line to the~/.bashrcfile to automatically set this environment variable when starting a new terminal.3 Installwebots_ros2You can either installwebots_ros2from the official released package, or install it from the latest up-to-date sources fromGithub.Installwebots_ros2distributed packageInstallwebots_ros2from sourcesRun the following command in the VM terminal.sudo apt-get install ros-jazzy-webots-ros2Install git.sudo apt-get install gitCreate a ROS 2 workspace with itssrcdirectory.mkdir -p ~/ros2_ws/srcSource the ROS 2 environment.source /opt/ros/jazzy/setup.bashRetrieve the sources from Github.cd ~/ros2_wsgit clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2Install the package dependencies.sudo apt install python3-pip python3-rosdep python3-colcon-common-extensionssudo rosdep init && rosdep updaterosdep install --from-paths src --ignore-src --rosdistro jazzyBuild the package usingcolcon.colcon buildSource this workspace.source install/local_setup.bash4 Launch thewebots_ros2_universal_robotexampleAs mentioned in previous sections, the package uses the shared folder to communicate with Webots from the VM to the host. +In order for Webots to be started on the host from the VM’s ROS package, a local TCP simulation server must be run.The server can be downloaded here:local_simulation_server.py. +Specify the Webots installation folder inWEBOTS_HOMEenvironment variable (e.g./Applications/Webots.app) and run the server using the following commands in a new terminal on the host (not in the VM):export WEBOTS_HOME=/Applications/Webots.apppython3 local_simulation_server.pyIn the VM, open a terminal and execute the following commands to start a package:First source the ROS 2 environment, if not done already.source /opt/ros/jazzy/setup.bashIf installed from sources, source your ROS 2 workspace, if not done already.cd ~/ros2_wssource install/local_setup.bashIf not already set in~/.bashrc, setWEBOTS_SHARED_FOLDER(see previous sections for details). +Be sure to change the paths according to the location of your respective directories.export WEBOTS_SHARED_FOLDER=/Users/username/shared:/home/ubuntu/sharedUse the ROS 2 launch command to start demo packages (e.g.webots_ros2_universal_robot).ros2 launch webots_ros2_universal_robot multirobot_launch.pyIf Webots is closed or the ROS 2 process is interrupted, the local server will automatically wait for a new package launch and the shared folder will be cleaned for the next run. + +Code Examples: + +Language: unknown +mkdir /home/ubuntu/shared + +Language: unknown +sudo mount -t 9p -o trans=virtio share /home/ubuntu/shared -oversion=9p2000.L + +Language: unknown +share /home/ubuntu/shared 9p trans=virtio,version=9p2000.L,rw,_netdev,nofail 0 0 + +Language: unknown +export WEBOTS_SHARED_FOLDER=/Users/username/shared:/home/ubuntu/shared + +Language: unknown +sudo apt-get install ros-jazzy-webots-ros2 + +Language: unknown +sudo apt-get install git + +Language: unknown +mkdir -p ~/ros2_ws/src + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +cd ~/ros2_wsgit clone --recurse-submodules https://github.com/cyberbotics/webots_ros2.git src/webots_ros2 + +Language: unknown +sudo apt install python3-pip python3-rosdep python3-colcon-common-extensionssudo rosdep init && rosdep updaterosdep install --from-paths src --ignore-src --rosdistro jazzy + +Language: unknown +colcon build + +Language: unknown +source install/local_setup.bash + +Language: unknown +export WEBOTS_HOME=/Applications/Webots.apppython3 local_simulation_server.py + +Language: unknown +source /opt/ros/jazzy/setup.bash + +Language: unknown +cd ~/ros2_wssource install/local_setup.bash + +Language: unknown +export WEBOTS_SHARED_FOLDER=/Users/username/shared:/home/ubuntu/shared + +Language: unknown +ros2 launch webots_ros2_universal_robot multirobot_launch.py diff --git "a/exported_docs/ros2/Installation_troubleshooting\357\203\201.txt" "b/exported_docs/ros2/Installation_troubleshooting\357\203\201.txt" new file mode 100644 index 0000000..2f9595f --- /dev/null +++ "b/exported_docs/ros2/Installation_troubleshooting\357\203\201.txt" @@ -0,0 +1,127 @@ +Title: Installation troubleshooting +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Installation-Troubleshooting.html +Section: Installation +-------------------------------------------------------------------------------- + +Installation troubleshootingTroubleshooting techniques for installation are sorted by the platforms they apply to.PlatformsGeneralLinuxmacOSWindowsGeneralGeneral troubleshooting techniques apply to all platforms.Enable multicastIn order to communicate successfully via DDS, the used network interface has to be multicast enabled. +We’ve seen in past experiences that this might not necessarily be enabled by default (on Ubuntu or OSX) when using the loopback adapter. +See theoriginal issueor aconversation on ros-answers. +You can verify that your current setup allows multicast with the ROS 2 tool:In Terminal 1:ros2multicastreceiveIn Terminal 2:ros2multicastsendIf the first command did not return a response similar to:Receivedfromxx.xxx.xxx.xx:43751:'Hello World!'then you will need to update your firewall configuration to allow multicast usingufw.sudoufwallowinprotoudpto224.0.0.0/4 +sudoufwallowinprotoudpfrom224.0.0.0/4You can check if the multicast flag is enabled for your network interface using theifconfigtool and looking forMULITCASTin the flags section:eno1:flags=4163<...,MULTICAST>...Import failing without library present on the systemSometimesrclpyfails to be imported because the expected C extension libraries are not found. +If so, compare the libraries present in the directory with the one mentioned in the error message. +Assuming a file with a similar name exists (same prefix like_rclpy.and same suffix like.sobut a different Python version / architecture) you are using a different Python interpreter than which was used to build the C extension. +Be sure to use the same Python interpreter as the one used to build the binary.For example, such a mismatch can crop up after an update of the OS. Then, rebuilding the workspace may fix the issue.LinuxInternal compiler errorIf you experience an ICE when trying to compile on a memory constrained platform like a Raspberry PI you might want to build single threaded (prefix the build invocation withMAKEFLAGS=-j1).Out of memoryTheros1_bridgein its current form requires 4Gb of free RAM to compile. +If you don’t have that amount of RAM available it’s suggested to useCOLCON_IGNOREin that folder and skip its compilation.Multiple host interferenceIf you’re running multiple instances on the same network you may get interference. +To avoid this you can set the environment variableROS_DOMAIN_IDto a different integer, the default is zero. +This will define the DDS domain id for your system.Exception sourcing setup.bashIf you encounter exceptions when trying to source the environment after building from source, try to upgradecolconrelated packages usingcolconversion-check# check if newer versions availablesudoaptinstallpython3-colcon*--only-upgrade# upgrade installed colcon packages to latest versionAnaconda Python Conflictcondadoes not work in conjunction with ROS 2. +Make sure that yourPATHenvironment variable does not have any conda paths in it. +You may have to check your.bashrcfor this line and comment it out.Cannot start rviz2rviz2may fail to start on a Wayland display system with errors like:QSocketNotifier:CanonlybeusedwiththreadsstartedwithQThread[INFO][1714730141.758659580][rviz2]:StereoisNOTSUPPORTED[INFO][1714730141.758813709][rviz2]:OpenGlversion:3.1(GLSL1.4)[ERROR][1714730141.797879232][rviz2]:rviz::RenderSystem:errorcreatingrenderwindow:RenderingAPIException:InvalidparentWindowHandle(wrongserverorscreen)inGLXWindow::createat./.obj-aarch64-linux-gnu/ogre_vendor-prefix/src/ogre_vendor/RenderSystems/GLSupport/src/GLX/OgreGLXWindow.cpp(line246)...[ERROR][1714730141.808124283][rviz2]:Unabletocreatetherenderingwindowafter100triesterminatecalledafterthrowinganinstanceof'std::runtime_error'what():Unabletocreatetherenderingwindowafter100triesAborted(coredumped)This is due to an incompatibility between Wayland and RViz2. +You may be able to workaround this problem by running RViz2 in X11 compatibility mode:QT_QPA_PLATFORM=xcbrviz2macOSSegmentation fault when usingpyenvpyenvseems to default to building Python with.afiles, but that causes issues withrclpy, so it’s recommended to build Python with Frameworks enabled on macOS when usingpyenv:https://github.com/pyenv/pyenv/wiki#how-to-build-cpython-with-framework-support-on-os-xLibrary not loaded; image not foundIf you are seeing library loading issues at runtime (either running tests or running nodes), such as the following:ImportError:dlopen(.../ros2_/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.so,2):Librarynotloaded:@rpath/librcl_interfaces__rosidl_typesupport_c.dylibReferencedfrom:.../ros2_/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.soReason:imagenotfoundThen you probably have System Integrity Protection enabled. +Followthese instructionsto disable System Integrity Protection (SIP).Qt build error:unknowntypename'Q_ENUM'If you see build errors related to Qt, e.g.:Infileincludedfrom/usr/local/opt/qt/lib/QtGui.framework/Headers/qguiapplication.h:46: +/usr/local/opt/qt/lib/QtGui.framework/Headers/qinputmethod.h:87:5:error:unknowntypename'Q_ENUM'Q_ENUM(Action)^you may be using qt4 instead of qt5: seehttps://github.com/ros2/ros2/issues/441Missing symbol when opencv (and therefore libjpeg, libtiff, and libpng) are installed with HomebrewIf you have opencv installed you might get this:dyld:Symbolnotfound:__cg_jpeg_resync_to_restartReferencedfrom:/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIOExpectedin:/usr/local/lib/libJPEG.dylibin/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO +/bin/sh:line1:25274Trace/BPTtrap:5/usr/local/bin/cmakeIf so, to build you’ll have to do this:$brewunlinklibpnglibtifflibjpegBut this will break opencv, so you’ll also need to update it to continue working:$sudoinstall_name_tool-change/usr/local/lib/libjpeg.8.dylib/usr/local/opt/jpeg/lib/libjpeg.8.dylib/usr/local/lib/libopencv_highgui.2.4.dylib +$sudoinstall_name_tool-change/usr/local/lib/libpng16.16.dylib/usr/local/opt/libpng/lib/libpng16.16.dylib/usr/local/lib/libopencv_highgui.2.4.dylib +$sudoinstall_name_tool-change/usr/local/lib/libtiff.5.dylib/usr/local/opt/libtiff/lib/libtiff.5.dylib/usr/local/lib/libopencv_highgui.2.4.dylib +$sudoinstall_name_tool-change/usr/local/lib/libjpeg.8.dylib/usr/local/opt/jpeg/lib/libjpeg.8.dylib/usr/local/Cellar/libtiff/4.0.4/lib/libtiff.5.dylibThe first command is necessary to avoid things built against the system libjpeg (etc.) from getting the version in /usr/local/lib. +The others are updating things built by Homebrew so that they can find the version of libjpeg (etc.) without having them in /usr/local/lib.Xcode-select error: toolxcodebuildrequires Xcode, but active developer directory is a command line instanceIf you recently installed Xcode, you may encounter this error:Xcode:xcode-select:error:tool'xcodebuild'requiresXcode, +butactivedeveloperdirectory'/Library/Developer/CommandLineTools'isacommandlinetoolsinstanceTo resolve this error, you will need to:Double check that you have the command line tool installed:$xcode-select--installAccept the terms and conditions of Xcode by typing in terminal:$sudoxcodebuild-licenseacceptEnsure Xcode app is in the/Applicationsdirectory (NOT/Users/{user}/Applications)Pointxcode-selectto the Xcode app Developer directory using the following command:$sudoxcode-select-s/Applications/Xcode.app/Contents/Developerrosdep install errorhomebrew:Failedtodetectsuccessfulinstallationof[qt5]While following theCreating a workspacetutorial, you might encounter the following error stating thatrosdepfailes to install Qt5.$rosdepinstall-i--from-pathsrc--rosdistrojazzy-y +executingcommand[brewinstallqt5]Warning:qt5.15.0isalreadyinstalledandup-to-date +Toreinstall5.15.0,run`brewreinstallqt`ERROR:thefollowingrosdepsfailedtoinstallhomebrew:Failedtodetectsuccessfulinstallationof[qt5]This error seems to stem from alinking issueand can be resolved by running the following command.$cd/usr/local/Cellar +$sudoln-sqtqt5Running therosdepcommand should now execute normally:$rosdepinstall-i--from-pathsrc--rosdistrojazzy-y#All required rosdeps installed successfullyWindowsImport failing even with library present on the systemSometimesrclpyfails to be imported because of some missing DLLs on your system. +If so, make sure to install all the dependencies listed in the “Installing prerequisites” sections of theinstallation instructions).If you are installing from binaries, you may need to update your dependencies: they must be the same version as those used to build the binaries.If you are still having issues, you can use theDependenciestool to determine which dependencies are missing on your system. +Use the tool to load the corresponding.pydfile, and it should report unavailableDLLmodules. +Be sure that the current workspace is sourced before you execute the tool, otherwise there will be unresolved ROS DLL files. +Use this information to install additional dependencies or adjust your path as necessary.CMake error setting modification timeIf you run into the CMake errorfileINSTALLcannotsetmodificationtimeon...when installing files it is likely that an anti virus software or Windows Defender are interfering with the build. E.g. for Windows Defender you can list the workspace location to be excluded to prevent it from scanning those files.260 character path limitTheinputlineistoolong. +Thesyntaxofthecommandisincorrect.Depending on your directory hierarchy, you may see path length limit errors when building ROS 2 from source or your own libraries.To allow deeper path lengths:Runregedit.exe, navigate toComputer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem, and setLongPathsEnabledto 0x00000001 (1).Hit the windows key and typeEditGroupPolicy. +Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem. +Right clickEnableWin32longpaths, click Edit. +In the dialog, select Enabled and click OK.Close and open your terminal to reset the environment and try building again.CMake packages unable to find asio, tinyxml2, tinyxml, or eigenWe’ve seen that sometimes the chocolatey packages forasio,tinyxml2, etc. do not add important registry entries and CMake will be unable to find them when building ROS 2. +We’ve not yet been able to identify the root cause, but uninstalling the chocolatey packages (with-nif the uninstall fails the first time), and then reinstalling them will fix the issue.patch.exe opens a new command window and asks for administratorThis will also cause the build of packages which need to use patch to fail, even you allow it to use administrator rights.chocouninstallpatch;colconbuild--cmake-clean-cache- This is a bug in theGNU Patch For Windows package. If this package is not installed, the build process will instead use the version of Patch distributed with git.Failed to load Fast RTPS shared libraryFast RTPS requiresmsvcr20.dll, which is part of theVisualC++RedistributablePackagesforVisualStudio2013. +Although it is usually installed by default in Windows 10, we know that some Windows 10-like versions don’t have it installed by default (e.g.: Windows Server 2019). +In case you don’t have it installed, you can download it fromhere.Failed to create processIf running a ROS binary gives the error:|failedtocreateprocess.It is likely the Python interpreter was not found. +For each executable, the shebang (first line) of the accompanying script is used, so make sure Python is available under the expected path (default:C:\Python38\).Binary installation specificIf your example does not start because of missing DLLs, please verify that all libraries from external dependencies such as OpenCV are located inside yourPATHvariable.If you forget to call thelocal_setup.batfile from your terminal, the demo programs will most likely crash immediately.Running RViz with WSL2If you are usingWSL2to run ROS 2 on Windows, you may run into an issue running RViz that looks like:$rviz2[INFO] [1695823660.091830699] [rviz2]: Stereo is NOT SUPPORTED[INFO] [1695823660.091943524] [rviz2]: OpenGl version: 4.1 (GLSL 4.1)D3D12: Removing Device.Segmentation faultOne possible solution to this is to force RViz to use software rendering:$exportLIBGL_ALWAYS_SOFTWARE=true$rviz2[INFO] [1695823660.091830699] [rviz2]: Stereo is NOT SUPPORTED + +Code Examples: + +Language: unknown +ros2multicastreceive + +Language: unknown +ros2multicastsend + +Language: unknown +Receivedfromxx.xxx.xxx.xx:43751:'Hello World!' + +Language: unknown +sudoufwallowinprotoudpto224.0.0.0/4 +sudoufwallowinprotoudpfrom224.0.0.0/4 + +Language: unknown +eno1:flags=4163<...,MULTICAST>... + +Language: unknown +colconversion-check# check if newer versions availablesudoaptinstallpython3-colcon*--only-upgrade# upgrade installed colcon packages to latest version + +Language: unknown +QSocketNotifier:CanonlybeusedwiththreadsstartedwithQThread[INFO][1714730141.758659580][rviz2]:StereoisNOTSUPPORTED[INFO][1714730141.758813709][rviz2]:OpenGlversion:3.1(GLSL1.4)[ERROR][1714730141.797879232][rviz2]:rviz::RenderSystem:errorcreatingrenderwindow:RenderingAPIException:InvalidparentWindowHandle(wrongserverorscreen)inGLXWindow::createat./.obj-aarch64-linux-gnu/ogre_vendor-prefix/src/ogre_vendor/RenderSystems/GLSupport/src/GLX/OgreGLXWindow.cpp(line246)...[ERROR][1714730141.808124283][rviz2]:Unabletocreatetherenderingwindowafter100triesterminatecalledafterthrowinganinstanceof'std::runtime_error'what():Unabletocreatetherenderingwindowafter100triesAborted(coredumped) + +Language: unknown +QT_QPA_PLATFORM=xcbrviz2 + +Language: unknown +ImportError:dlopen(.../ros2_/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.so,2):Librarynotloaded:@rpath/librcl_interfaces__rosidl_typesupport_c.dylibReferencedfrom:.../ros2_/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.soReason:imagenotfound + +Language: unknown +Infileincludedfrom/usr/local/opt/qt/lib/QtGui.framework/Headers/qguiapplication.h:46: +/usr/local/opt/qt/lib/QtGui.framework/Headers/qinputmethod.h:87:5:error:unknowntypename'Q_ENUM'Q_ENUM(Action)^ + +Language: unknown +dyld:Symbolnotfound:__cg_jpeg_resync_to_restartReferencedfrom:/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIOExpectedin:/usr/local/lib/libJPEG.dylibin/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO +/bin/sh:line1:25274Trace/BPTtrap:5/usr/local/bin/cmake + +Language: unknown +$brewunlinklibpnglibtifflibjpeg + +Language: unknown +$sudoinstall_name_tool-change/usr/local/lib/libjpeg.8.dylib/usr/local/opt/jpeg/lib/libjpeg.8.dylib/usr/local/lib/libopencv_highgui.2.4.dylib +$sudoinstall_name_tool-change/usr/local/lib/libpng16.16.dylib/usr/local/opt/libpng/lib/libpng16.16.dylib/usr/local/lib/libopencv_highgui.2.4.dylib +$sudoinstall_name_tool-change/usr/local/lib/libtiff.5.dylib/usr/local/opt/libtiff/lib/libtiff.5.dylib/usr/local/lib/libopencv_highgui.2.4.dylib +$sudoinstall_name_tool-change/usr/local/lib/libjpeg.8.dylib/usr/local/opt/jpeg/lib/libjpeg.8.dylib/usr/local/Cellar/libtiff/4.0.4/lib/libtiff.5.dylib + +Language: unknown +Xcode:xcode-select:error:tool'xcodebuild'requiresXcode, +butactivedeveloperdirectory'/Library/Developer/CommandLineTools'isacommandlinetoolsinstance + +Language: unknown +$xcode-select--install + +Language: unknown +$sudoxcodebuild-licenseaccept + +Language: unknown +$sudoxcode-select-s/Applications/Xcode.app/Contents/Developer + +Language: unknown +$rosdepinstall-i--from-pathsrc--rosdistrojazzy-y +executingcommand[brewinstallqt5]Warning:qt5.15.0isalreadyinstalledandup-to-date +Toreinstall5.15.0,run`brewreinstallqt`ERROR:thefollowingrosdepsfailedtoinstallhomebrew:Failedtodetectsuccessfulinstallationof[qt5] + +Language: unknown +$cd/usr/local/Cellar +$sudoln-sqtqt5 + +Language: unknown +$rosdepinstall-i--from-pathsrc--rosdistrojazzy-y#All required rosdeps installed successfully + +Language: unknown +Theinputlineistoolong. +Thesyntaxofthecommandisincorrect. + +Language: unknown +|failedtocreateprocess. + +Language: unknown +$rviz2[INFO] [1695823660.091830699] [rviz2]: Stereo is NOT SUPPORTED[INFO] [1695823660.091943524] [rviz2]: OpenGl version: 4.1 (GLSL 4.1)D3D12: Removing Device.Segmentation fault + +Language: unknown +$exportLIBGL_ALWAYS_SOFTWARE=true$rviz2[INFO] [1695823660.091830699] [rviz2]: Stereo is NOT SUPPORTED diff --git "a/exported_docs/ros2/Installation\357\203\201.txt" "b/exported_docs/ros2/Installation\357\203\201.txt" new file mode 100644 index 0000000..fac9d5d --- /dev/null +++ "b/exported_docs/ros2/Installation\357\203\201.txt" @@ -0,0 +1,15 @@ +Title: Installation +URL: https://docs.ros.org/en/iron/Installation.html +Section: Installation +-------------------------------------------------------------------------------- + +You're reading the documentation for an older, but still supported, version of ROS 2. + For information on the latest version, please have a look atJazzy.InstallationOptions for installing ROS 2 Iron Irwini:Binary packagesBinaries are only created for the Tier 1 operating systems listed inREP-2000. +If you are not running any of the following operating systems you may need to build from source or use acontainer solutionto run ROS 2 on your platform.We provide ROS 2 binary packages for the following platforms:Ubuntu Linux - Jammy Jellyfish (22.04)deb packages(recommended)binary archiveRHEL 9RPM packages(recommended)binary archiveWindows 10Windows Binary (VS 2019)Building from sourceWe support building ROS 2 from source on the following platforms:Ubuntu Linux 22.04Windows 10RHEL-9/FedoramacOSWhich install should you choose?Installing from binary packages or from source will both result in a fully-functional and usable ROS 2 install. +Differences between the options depend on what you plan to do with ROS 2.Binary packagesare for general use and provide an already-built install of ROS 2. +This is great for people who want to dive in and start using ROS 2 as-is, right away.Linux users have two options for installing binary packages:Packages (debs or RPMS, depending on the platform)binary archiveInstalling from packages is the recommended method, as it installs necessary dependencies automatically and also updates alongside regular system updates. +However, you need root access in order to install deb packages. +If you don’t have root access, the binary archive is the next best choice.Windows users who choose to install from binary packages only have the binary archive option +(deb packages are exclusive to Ubuntu/Debian).Building from sourceis meant for developers looking to alter or explicitly omit parts of ROS 2’s base. +It is also recommended for platforms that don’t support binaries. +Building from source also gives you the option to install the absolute latest version of ROS 2.Contributing to ROS 2 core?If you plan to contribute directly to ROS 2 core packages, you can install thelatest development from sourcewhich shares installation instructions with theRolling distribution. \ No newline at end of file diff --git "a/exported_docs/ros2/Interfaces\357\203\201.txt" "b/exported_docs/ros2/Interfaces\357\203\201.txt" new file mode 100644 index 0000000..164dd77 --- /dev/null +++ "b/exported_docs/ros2/Interfaces\357\203\201.txt" @@ -0,0 +1,94 @@ +Title: Interfaces +URL: https://docs.ros.org/en/jazzy/Concepts/Basic/About-Interfaces.html +Section: Installation +-------------------------------------------------------------------------------- + +InterfacesTable of ContentsBackgroundMessagesFieldsField typesField namesField default valueConstantsServicesActionsBackgroundROS applications typically communicate through interfaces of one of three types:topics,services, oractions. +ROS 2 uses a simplified description language, the interface definition language (IDL), to describe these interfaces. +This description makes it easy for ROS tools to automatically generate source code for the interface type in several target languages.In this document we will describe the supported types:msg:.msgfiles are simple text files that describe the fields of a ROS message. They are used to generate source code for messages in different languages.srv:.srvfiles describe a service. They are composed of two parts: a request and a response. The request and response are message declarations.action:.actionfiles describe actions. They are composed of three parts: a goal, a result, and feedback. +Each part is a message declaration itself.MessagesMessages are a way for a ROS 2 node to send data on the network to other ROS nodes, with no response expected. +For instance, if a ROS 2 node reads temperature data from a sensor, it can then publish that data on the ROS 2 network using aTemperaturemessage. +Other nodes on the ROS 2 network can subscribe to that data and receive theTemperaturemessage.Messages are described and defined in.msgfiles in themsg/directory of a ROS package..msgfiles are composed of two parts: fields and constants.FieldsEach field consists of a type and a name, separated by a space, i.e:fieldtype1fieldname1 +fieldtype2fieldname2 +fieldtype3fieldname3For example:int32my_int +stringmy_stringField typesField types can be:a built-in-typenames of Message descriptions defined on their own, such as “geometry_msgs/PoseStamped”Built-in-types currently supported:Type nameC++PythonDDS typeboolboolbuiltins.boolbooleanbyteuint8_tbuiltins.bytes*octetcharcharbuiltins.int*charfloat32floatbuiltins.float*floatfloat64doublebuiltins.float*doubleint8int8_tbuiltins.int*octetuint8uint8_tbuiltins.int*octetint16int16_tbuiltins.int*shortuint16uint16_tbuiltins.int*unsigned shortint32int32_tbuiltins.int*longuint32uint32_tbuiltins.int*unsigned longint64int64_tbuiltins.int*long longuint64uint64_tbuiltins.int*unsigned long longstringstd::stringbuiltins.strstringwstringstd::u16stringbuiltins.strwstringEvery built-in-type can be used to define arrays:Type nameC++PythonDDS typestatic arraystd::arraybuiltins.list*T[N]unbounded dynamic arraystd::vectorbuiltins.listsequencebounded dynamic arraycustom_classbuiltins.list*sequencebounded stringstd::stringbuiltins.str*stringAll types that are more permissive than their ROS definition enforce the ROS constraints in range and length by software.Example of message definition using arrays and bounded types:int32[]unbounded_integer_array +int32[5]five_integers_array +int32[<=5]up_to_five_integers_array + +stringstring_of_unbounded_size +string<=10up_to_ten_characters_string + +string[<=5]up_to_five_unbounded_strings +string<=10[]unbounded_array_of_strings_up_to_ten_characters_each +string<=10[<=5]up_to_five_strings_up_to_ten_characters_eachField namesField names must be lowercase alphanumeric characters with underscores for separating words. +They must start with an alphabetic character, and they must not end with an underscore or have two consecutive underscores.Field default valueDefault values can be set to any field in the message type. +Currently default values are not supported for string arrays and complex types (i.e. types not present in the built-in-types table above; that applies to all nested messages).Defining a default value is done by adding a third element to the field definition line, i.e:fieldtypefieldnamefielddefaultvalueFor example:uint8x42int16y-2000 +stringfull_name"John Doe"int32[]samples[-200,-100,0,100,200]Notestring values must be defined in single'or double"quotescurrently string values are not escapedConstantsEach constant definition is like a field description with a default value, except that this value can never be changed programatically. +This value assignment is indicated by use of an equal ‘=’ sign, e.g.constanttypeCONSTANTNAME=constantvalueFor example:int32X=123int32Y=-123 +stringFOO="foo"stringEXAMPLE='bar'NoteConstants names have to be UPPERCASEServicesServices are a request/response communication, where the client (requester) is waiting for the server (responder) to make a short computation and return a result.Services are described and defined in.srvfiles in thesrv/directory of a ROS package.A service description file consists of a request and a response msg type, separated by---. +Any two.msgfiles concatenated with a---are a legal service description.Here is a very simple example of a service that takes in a string and returns a string:stringstr +--- +stringstrWe can of course get much more complicated (if you want to refer to a message from the same package you must not mention the package name):# request constantsint8FOO=1int8BAR=2# request fieldsint8foobar +another_pkg/AnotherMessagemsg +---# response constantsuint32SECRET=123456# response fieldsanother_pkg/YetAnotherMessageval +CustomMessageDefinedInThisPackagevalue +uint32an_integerYou cannot embed another service inside of a service.ActionsActions are a long-running request/response communication, where the action client (requester) is waiting for the action server (the responder) to take some action and return a result. +In contrast to services, actions can be long-running (many seconds or minutes), provide feedback while they are happening, and can be interrupted.Action definitions have the following form:------Like services, the request fields are before and the response fields are after the first triple-dash (---), respectively. +There is also a third set of fields after the second triple-dash, which is the fields to be sent when sending feedback.There can be arbitrary numbers of request fields (including zero), arbitrary numbers of response fields (including zero), and arbitrary numbers of feedback fields (including zero).The,, andfollow all of the same rules as thefor a message. +The,, andfollow all of the same rules as thefor a message.For instance, theFibonacciaction definition contains the following:int32order---int32[]sequence---int32[]sequenceThis is an action definition where the action client is sending a singleint32field representing the number of Fibonacci steps to take, and expecting the action server to produce an array ofint32containing the complete steps. +Along the way, the action server may also provide an intermediate array ofint32containing the steps accomplished up until a certain point. + +Code Examples: + +Language: unknown +fieldtype1fieldname1 +fieldtype2fieldname2 +fieldtype3fieldname3 + +Language: unknown +int32my_int +stringmy_string + +Language: unknown +int32[]unbounded_integer_array +int32[5]five_integers_array +int32[<=5]up_to_five_integers_array + +stringstring_of_unbounded_size +string<=10up_to_ten_characters_string + +string[<=5]up_to_five_unbounded_strings +string<=10[]unbounded_array_of_strings_up_to_ten_characters_each +string<=10[<=5]up_to_five_strings_up_to_ten_characters_each + +Language: unknown +fieldtypefieldnamefielddefaultvalue + +Language: unknown +uint8x42int16y-2000 +stringfull_name"John Doe"int32[]samples[-200,-100,0,100,200] + +Language: unknown +constanttypeCONSTANTNAME=constantvalue + +Language: unknown +int32X=123int32Y=-123 +stringFOO="foo"stringEXAMPLE='bar' + +Language: unknown +stringstr +--- +stringstr + +Language: unknown +# request constantsint8FOO=1int8BAR=2# request fieldsint8foobar +another_pkg/AnotherMessagemsg +---# response constantsuint32SECRET=123456# response fieldsanother_pkg/YetAnotherMessageval +CustomMessageDefinedInThisPackagevalue +uint32an_integer + +Language: unknown +------ + +Language: unknown +int32order---int32[]sequence---int32[]sequence diff --git "a/exported_docs/ros2/Iron_Irwini_(iron)\357\203\201.txt" "b/exported_docs/ros2/Iron_Irwini_(iron)\357\203\201.txt" new file mode 100644 index 0000000..6d23dc6 --- /dev/null +++ "b/exported_docs/ros2/Iron_Irwini_(iron)\357\203\201.txt" @@ -0,0 +1,162 @@ +Title: Iron Irwini (iron) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Iron-Irwini.html +Section: Installation +-------------------------------------------------------------------------------- + +Iron Irwini (iron)Table of ContentsSupported PlatformsInstallationNew features in this ROS 2 releaseAPI documentation generation for Python packagesService introspectionPre and post set parameter callback supportImproved discovery optionsMatched eventsExternal configuration services of loggersType Description DistributionDynamic Types and Dynamic Messageslaunchlaunch_roslaunch_testingrclcpprclpyros2paramros2topicChanges since the Humble releaseChange to the default console logging file flushing behaviorament_cmake_autoament_cmake_noseament_lintcamera_info_managerlaunchlaunch_roslaunch_xmllaunch_yamlmessage_filtersrcl_yaml_param_parserrclcpprclpyrcutilsrmwrmw_dds_commonros2topicrosbag2rosidl_pythonrviztracetoolsKnown IssuesRelease TimelineDevelopment progressIron Irwiniis the ninth release of ROS 2. +What follows is highlights of the important changes and features in Iron Irwini since the last release. +For a list of all of the changes since Humble, see thelong form changelog.Supported PlatformsIron Irwini is primarily supported on the following platforms:Tier 1 platforms:Ubuntu 22.04 (Jammy):amd64andarm64Windows 10 (Visual Studio 2019):amd64Tier 2 platforms:RHEL 9:amd64Tier 3 platforms:macOS:amd64Debian Bullseye:amd64For more information about RMW implementations, compiler / interpreter versions, and system dependency versions seeREP 2000.InstallationInstall Iron IrwiniNew features in this ROS 2 releaseAPI documentation generation for Python packagesROS 2 has had automatic API documentation for C++ packages for several releases, e.g.https://docs.ros.org/en/rolling/p/rclcpp/generated/index.html. +Iron adds automatic API documentation for Python packages as well, e.g.https://docs.ros.org/en/rolling/p/rclpy/rclpy.html.Seehttps://github.com/ros-infrastructure/rosdoc2/pull/28,https://github.com/ros-infrastructure/rosdoc2/pull/49,https://github.com/ros-infrastructure/rosdoc2/pull/51, andhttps://github.com/ros-infrastructure/rosdoc2/pull/52for more details.Service introspectionIt is now possible to enable service introspection on a per-service basis. +When enabled, this allows users to see the metadata associated with the client requesting a service, the server accepting the request, the server sending the response, and the client accepting the response. +Optionally, the contents of the client/server requests/responses can also be introspected. +All of the information is published on a hidden topic generated from the name of the service. +So if the service is called/myservice, then the information will be published on/myservice/_service_event.Note that this functionality is disabled by default; to enable it, users must callconfigure_introspectionafter creating a server client or server. +There are examples showing how to do this inhttps://github.com/ros2/demos/tree/iron/demo_nodes_cpp/src/services(C++) andhttps://github.com/ros2/demos/blob/iron/demo_nodes_py/demo_nodes_py/services/introspection.py(Python).SeeREP 2012and the tracking bug athttps://github.com/ros2/ros2/issues/1285for more information.Pre and post set parameter callback supportFor many releases now, users could register a callback to be called when parameters on a node were changed by an external entity (likeros2paramset). +This callback could examine the changed parameter types and values, and reject the whole lot if one of them didn’t meet certain criteria. +However, it could not modify the parameter list, nor should it have modified state (since there might be other callbacks after the set one that would reject the parameters).This release adds in a pre and post callback. +The callbacks are called in this order:The “pre” set parameter callback, which can modify the list of parameters based on arbitrary criteria.The “set” parameter callback, which cannot modify the list and should only accept or reject the parameters based on their type and value (this is the existing callback).The “post” set parameter callback, which can make state changes based on parameters and is only called if the previous two callbacks are successful.There are examples of this in action inhttps://github.com/ros2/demos/blob/iron/demo_nodes_cpp/src/parameters/set_parameters_callback.cpp(C++) andhttps://github.com/ros2/demos/blob/iron/demo_nodes_py/demo_nodes_py/parameters/set_parameters_callback.py(Python).Seehttps://github.com/ros2/rclcpp/pull/1947,https://github.com/ros2/rclpy/pull/966, andhttps://github.com/ros2/demos/pull/565for more information.Improved discovery optionsPrevious ROS 2 versions offered limited discovery options. +The default behavior for DDS based RMW implementations was to discover any node reachable via multicast. +It could be limited to the same machine by setting the environment variableROS_LOCALHOST_ONLY, but any additional configuration required configuring the middleware directly, usually via middleware specific XML files and environment variables. +ROS Iron retains the same default discovery behavior, but deprecatesROS_LOCALHOST_ONLYin favor of more granular options.ROS_AUTOMATIC_DISCOVERY_RANGEcontrols how far ROS nodes will try to discover each other. Valid options are:SUBNET- The default, and for DDS-based middlewares it will discover any node reachable via multicast.LOCALHOST- Will only try to discover other nodes on the same machine.OFF- Will not attempt to discover any other nodes automatically, even on the same machine.SYSTEM_DEFAULT- Will not change any discovery settings. This is useful when you already have custom settings for your middleware and don’t want ROS to change them.ROS_STATIC_PEERS- A semicolon (;) separated list of addresses that ROS should try to discover nodes on. This allows the user to connect to nodes on specifc machines (as long as their discovery range is not set toOFF).For example, you might have several robots withROS_AUTOMATIC_DISCOVERY_RANGEset toLOCALHOSTso they don’t communicate with each other. +When you want to connect RViz to one of them, you add it’s address toROS_STATIC_PEERSin your terminal. +Now you can use ROS 2 CLI and visualization tools to interact with the robot.Seehttps://github.com/ros2/ros2/issues/1359for more information about this feature.Matched eventsIn addition to QoS events, matched events can be generated when any publisher and subscription establishes or drops the connection between them. +Users can provide each publisher and subscription with callback functions that are triggered by matched events and handle them in a way they see fit, similar to how messages received on a topic are handled.publisher: this event happens when it finds a subscription which matches the topic and has compatible QoS or a connected subscription is disconnected.subscription: this event happens when it finds a publisher which matches the topic and has compatible QoS or a connected publisher is disconnected.See the tracking issue athttps://github.com/ros2/rmw/issues/330for more information.C++ Demo of Matched Events:https://github.com/ros2/demos/blob/iron/demo_nodes_cpp/src/events/matched_event_detect.cppPython Demo of Matched Events:https://github.com/ros2/demos/blob/iron/demo_nodes_py/demo_nodes_py/events/matched_event_detect.pyExternal configuration services of loggersIt is now possible to configure node logger levels remotely via a service. +When theenable_logger_serviceoption is enabled during node creation, theset_logger_levelsandget_logger_levelsservices will be available.Be advised that theenable_logger_serviceoption is disabled by default, so the user needs to enable this option on node creation.Seehttps://github.com/ros2/ros2/issues/1355for more information.Type Description DistributionIt is now possible to communicate information about the types of ROS 2 messages, so that systems with potentially-different types of the same name may discover their compatibility more transparently. +This umbrella of capabilities, which is defined by a subset of REP-2011: Evolving Message Types, has had many parts land in Iron.First, the introduction of the new packagetype_description_interfacesprovides a common way to communicate the descriptions of ROS 2 communication interface types (msg, srv, action).Next, a method to hash type descriptions has been decided on, the ROS Interface Hashing Standard (RIHS) - starting with the first version RIHS01. +RIHS hashes are automatically calculated for all compiled ROS types at build time, and baked into the generated code so that they can be inspected. +These hashes are also communicated automatically during discovery, and included inrmw_topic_endpoint_info_tfor graph introspection queries such asget_publishers_info_by_topic.The fullTypeDescriptiondata structure, as well as the raw source text (such as.msgfile) that were used to generate it are now baked in by default to the message libraries, so they can be used bytypesupportor end users. +While we expect this data to provide value to most users, some users trying to minimize bytes in their install space can disable the feature when building ROS 2 Core by defining the CMake variableROSIDL_GENERATOR_C_DISABLE_TYPE_DESCRIPTION_CODEGEN.Finally, the new servicetype_description_interfaces/GetTypeDescription.srvhas been defined to allow nodes, on encountering an unknown RIHS type hash, to request the full definition from the node advertising that type. +Work is in progress to provide this feature natively in ROS 2 Nodes, as an optional switch on node construction. +This feature has not yet shipped, but is expected to be backported into Iron sometime mid-2023. +Meanwhile, user nodes could implement this service indepedently, using the stable service interface.SeeREP 2011for the design proposal. +SeeType Description Distributionfor tracking development on the feature set.Dynamic Types and Dynamic MessagesAlongside the type description distribution feature mentioned above, is the ability to construct and access dynamically created types at runtime (i.e., dynamic types). +This feature is available in Iron for Fast DDS andrcl, with newrmwinterfaces for supporting the taking of messages as dynamic messages (i.e., messages built from or following the structure of the dynamic type).First, utilities were introduced intorosidlto aid in the construction and manipulation of type descriptions.Next, therosidl_dynamic_typesupportpackage was written and provides a middleware-agnostic interface to construct dynamic types and dynamic messages at runtime. +Types can be constructed at runtime either programmatically, or by parsing atype_description_interfaces/TypeDescriptionmessage.NoteTherosidl_dynamic_typesupportlibrary requires serialization support libraries to implement the middleware-specific dynamic type behavior. +A serialization support library for Fast DDS was implemented inrosidl_dynamic_typesupport_fastrtps. +Ideally more middlewares will implement support libraries, expanding the number of middlewares that support this feature.Finally, to support the use of dynamic types and dynamic messages, new methods were added tormwandrclthat support:The ability to obtain of middleware-specific serialization supportThe ability to construct message type support at runtime that use dynamic typesThe ability to take dynamic messages using dynamic typeWork is in progress to enable the use of dynamic types to create subscriptions in the client libraries (see therclcppissue below), though it is uncertain when the feature will land or be backported. +This will allow users to subscribe to topics whose type descriptions are only known at runtime. +In the meantime, users may write their own subscriptions that subscribe to dynamic types by using the newrmwandrclfeatures introduced as part of this feature set.SeeREP 2011for the design proposal. +SeeDynamic Subscriptionfor tracking development on the feature set, withrclcppneeding the bulk of the work.launchPythonExpressionnow supports importing modulesIt is now possible to have a launchPythonExpressionimport modules before performing the evaluation. +This can be useful for pulling in additional functionality to be used when evaluating an expression.Seehttps://github.com/ros2/launch/pull/655for more information.ReadyToTestcan be called from an event handlerIt is now possible to register an event handler that usesReadyToTestin its output. +This can be useful for doing things like downloading an asset before allowing a test to run.Seehttps://github.com/ros2/launch/pull/665for more information.Addition ofAnySubstitutionandAllSubstitutionIt is now possible to specify a substitution to happen when any of the input arguments are true (AnySubstitution), or when all of the input arguments are true (AllSubstitution).Seehttps://github.com/ros2/launch/pull/649for more details.Addition of a new substitution to get the launch logging directoryIt is now possible to use a substitution calledLaunchLogDirto get the current logging directory for launch.Seehttps://github.com/ros2/launch/pull/652for more details.launch_rosAdd aLifecycleTransitionactionIt is now possible to send a transition signal to a lifecycle node via the newLifeCycleTransitionaction.Seehttps://github.com/ros2/launch_ros/pull/317for more information.Add aSetROSLogDiractionIt is now possible to configure the directory used for logging via theSetROSLogDiraction.Seehttps://github.com/ros2/launch_ros/pull/325for more information.Ability to specify a condition to aComposableNodeIt is now possible to specify a condition that must be satisfied in order for aComposableNodeto be inserted into its container.Seehttps://github.com/ros2/launch_ros/pull/311for more information.launch_testingTimeout for process startup is now configurablePrior to this release, theReadyToTestaction would wait exactly 15 seconds for processes to start up. +If the processes took longer than that, they would fail. +There is now a new decorator calledready_to_test_action_timeoutthat allows the user to configure the amount of time to wait for the processes to start.Seehttps://github.com/ros2/launch/pull/625for more information.rclcppAddition of a new paradigm for handlingNodeandLifecycleNodeTheNodeandLifecycleNodeclasses are related in that they both provide the same base set of methods (thoughLifecycleNodeprovides additional methods as well). +Due to various implementation considerations, they are not derived from a common base class.This has led to some trouble for downstream code that wants to accept either aNodeor aLifecycleNode. +One solution is to have two method signatures, one that accepts aNodeand one that accepts aLifecycleNode. +The other, recommended solution is to have a method that accepts the “node interfaces” pointers that can be accessed from both classes, e.g.voiddo_thing(rclcpp::node_interfaces::NodeGraphInterfacegraph){fprintf(stderr,"Doing a thing\n");}voiddo_thing(rclcpp::Node::SharedPtrnode){do_thing(node->get_node_graph_interface());}voiddo_thing(rclcpp::LifecycleNode::SharedPtrnode){do_thing(node->get_node_graph_interface());}This works, but can get a bit unwieldy when many node interfaces are needed. +To make this a bit better, there is now a newNodeInterfacesclass that can be constructed to contain the interfaces, and then be used by other code.There are examples on how to use this inhttps://github.com/ros2/rclcpp/pull/2041.Introduction of a new executor type: the Events ExecutorTheEventsExecutorfrom iRobot has been merged into the mainrclcppcodebase. +This alternative executor implementation uses event-driven callbacks from the middleware implementations to fire callbacks at therclcpplayer. +In addition to the push-based model, theEventsExecutoralso moves timer management into a separate thread, which can allow for more accurate results and lower overhead, especially with many timers.TheEventsExecutorhas a substantial set of documentation and use-in-practice that make it a strong candidate for inclusion in therclcppcodebase. +For information about the initial implementation proposal as well as performance benchmarks, seehttps://discourse.ros.org/t/ros2-middleware-change-proposal/15863. +For more information about the design, see the design PR:https://github.com/ros2/design/pull/305.Since the API is the same, trying theEventsExecutoris as straightforward as replacing your current Executor implementation (eg.SingleThreadedExecutor):#includeusingrclcpp::experimental::executors::EventsExecutor;EventsExecutorexecutor;executor.add_node(node);executor.spin();NoteTheEventsExecutorandTimersManagerare currently in theexperimentalnamespace. +While it has been used as a standalone implementation for some timehttps://github.com/irobot-ros/events-executor, it was decided to use theexperimentalnamespace for at least one release to give latitude in changing the API within the release. +Use caution as it will not be subject to the same API/ABI guarantees that the non-experimental code has.rclpyAbility to wait for another node to join the graphIt is now possible to wait for another node to join the network graph with code like the following:node.wait_for_node('/fully_qualified_node_name')Seehttps://github.com/ros2/rclpy/pull/930for more information.Implementation ofAsyncParameterClientrclpynow has anAsyncParameterClientclass, bringing it to feature parity withrclcpp. +This class is used to perform parameter actions on a remote node without blocking the calling node.Seehttps://github.com/ros2/rclpy/pull/959for more information and examples.Subscription callbacks can now optionally get the message infoIt is now possible to register for a subscription callback with a function signature that takes both the message, and the message info, like:defmsg_info_cb(msg,msg_info):print('Message info:',msg_info)node.create_subscription(msg_type=std_msgs.msg.String,topic='/chatter',qos_profile=10,callback=msg_info_cb)The message info structure contains various pieces of information like the sequence number of the message, the source and received timestamps, and the GID of the publisher.Seehttps://github.com/ros2/rclpy/pull/922for more information.Optional argument that hides assertions for messages classAll message classes now include a new optional argument that allows the hiding of assertions for each field type from the message. +By default, assertions are hidden, which provides a performance improvement during runtime. +In order to enable the assertions for development/debugging purposes, you are given two choices:Define the environment variableROS_PYTHON_CHECK_FIELDSto'1'(this would affect all the messages in your project):importosfromstd_msgs.msgimportStringos.environ['ROS_PYTHON_CHECK_FIELDS']='1'new_message=String()Select the specific behavior for a single message by explicitly defining the new argument in the constructor:fromstd_msgs.msgimportStringnew_message=String(check_fields=True)Seehttps://github.com/ros2/rosidl_python/pull/194for more information.ros2paramOption to timeout when waiting for a node withros2paramIt is now possible to have the variousros2paramcommands timeout by passing--timeoutto the command.Seehttps://github.com/ros2/ros2cli/pull/802for more information.Deprecated options were removed--output-dirand--printoptions withdumpcommand have been removed.Seehttps://github.com/ros2/ros2cli/pull/824for more information.ros2topicnowas keyword forbuiltin_interfaces.msg.Timeandautoforstd_msgs.msg.Headerros2topicpubnow allows to set abuiltin_interfaces.msg.Timemessage to the current time via thenowkeyword. +Similarly, astd_msg.msg.Headermessage will be automatically generated when passed the keywordauto. +This behavior matches that of ROS 1’srostopic(http://wiki.ros.org/ROS/YAMLCommandLine#Headers.2Ftimestamps)Related PR:ros2/ros2cli#749ros2topicpubcan be configured to wait a maximum amount of timeThe commandros2topicpub-w1will wait for at least that number of subscribers before publishing a message. +This release adds in a--max-wait-timeoption so that the command will only wait a maximum amount of time before quitting if no subscribers are seen.Seehttps://github.com/ros2/ros2cli/pull/800for more information.ros2topicechocan be configured to wait a maximum amount of timeThe commandros2topicechonow accepts a--timeoutoption, which controls the maximum amount of time that the command will wait for a publication to happen.Seehttps://github.com/ros2/ros2cli/pull/792for more information.Deprecated option was removed--lost-messagesoption withechocommand has been removed.Seehttps://github.com/ros2/ros2cli/pull/824for more information.Changes since the Humble releaseChange to the default console logging file flushing behaviorThis specifically applies to the defaultspdlogbased logging backend in ROS 2, implemented inrcl_logging_spdlog. +Log file flushing was changed to flush every time an “error” log message is used, e.g. eachRCLCPP_ERROR()call, and also periodically every five seconds.Previously,spdlogwas used without configuring anything other than creating the sink for logging to a file.We tested the change and did not find that the CPU overhead was significant, even on machines with slow disks (e.g. sd cards). +However, if this change is causing you problems, you can get the old behavior by setting theRCL_LOGGING_SPDLOG_EXPERIMENTAL_OLD_FLUSHING_BEHAVIOR=1environment variable.Later we would like to have support for a full configuration file (see:https://github.com/ros2/rcl_logging/issues/92), giving you more flexibility in how the logging is done, but that is work that is only planned right now.Therefore,this environment variable should be considered experimental and subject to removal without deprecation in the future, when we add config file support for thercl_logging_spdloglogging backend.See this pull request for more details about the change:https://github.com/ros2/rcl_logging/pull/95ament_cmake_autoInclude dependencies are now marked as SYSTEMWhen usingament_auto_add_executableorament_auto_add_library, dependencies are now automatically added asSYSTEM. +This means that warnings in the header files of the dependencies will not be reported.Seehttps://github.com/ament/ament_cmake/pull/385for more details.ament_cmake_nosePackage has been deprecated and removedThe Pythonnosepackage has long been deprecated. +Since none of the open-source packages currently released into Humble or Rolling currently depend on it, this release deprecates and removes the ament wrapper around it.Seehttps://github.com/ament/ament_cmake/pull/415for more information.ament_lintFiles can be excluded from linter checksCertain files can now be excluded from linter checks by setting theAMENT_LINT_AUTO_FILE_EXCLUDECMake variable before callingament_lint_auto_find_test_dependencies.Seehttps://github.com/ament/ament_lint/pull/386for more information.camera_info_managerLifecycle node supportcamera_info_managernow supports lifecycle nodes in additional to regular ROS 2 nodes.Seehttps://github.com/ros-perception/image_common/pull/190for more information.launchLaunchConfigurationEqualsandLaunchConfigurationNotEqualsare deprecatedTheLaunchConfigurationEqualsandLaunchConfigurationNotEqualsconditions are deprecated, and will be removed in a future release. +Instead, the more universalEqualsandNotEqualssubstitutions should be used instead.Seehttps://github.com/ros2/launch/pull/649for more details.launch_rosRenamed classes which usedRosin the name to useROSin line with PEP8Classes that were changed:launch_ros.actions.RosTimer->launch_ros.actions.ROSTimerlaunch_ros.actions.PushRosNamespace->launch.actions.PushROSNamespaceThe old class names are still there, but will be deprecated.Seehttps://github.com/ros2/launch_ros/pull/326for more information.launch_xmlExposeemulate_ttyto XML frontendIt has been possible for several releases to have thelaunchPython code use pseudo-terminals to emulate a TTY (and hence do things like print colors). +That functionality is now available in the XML frontend by passing theemulate_ttyargument to an executable command.Seehttps://github.com/ros2/launch/pull/669for more information.Exposesigterm_timeoutandsigkill_timeoutto XML frontendIt has been possible for several releases to configure the maximum timeout value for the SIGTERM and SIGKILL signals in thelaunchPython code. +That functionality is now available in the XML frontend by passing thesigterm_timeoutorsigkill_timeoutargument to an executable command.Seehttps://github.com/ros2/launch/pull/667for more information.launch_yamlExposeemulate_ttyto YAML frontendIt has been possible for several releases to have thelaunchPython code use pseudo-terminals to emulate a TTY (and hence do things like print colors). +That functionality is now available in the YAML frontend by passing theemulate_ttyargument to an executable command.Seehttps://github.com/ros2/launch/pull/669for more information.Exposesigterm_timeoutandsigkill_timeoutto YAML frontendIt has been possible for several releases to configure the maximum timeout value for the SIGTERM and SIGKILL signals in thelaunchPython code. +That functionality is now available in the YAML frontend by passing thesigterm_timeoutorsigkill_timeoutargument to an executable command.Seehttps://github.com/ros2/launch/pull/667for more information.message_filtersNew approximate time policyAdd in a simpler approximate time policy calledApproximateEpsilonTime. +This time policy works likeExactTime, but allows timestamps being within a epsilon tolerance. +Seehttps://github.com/ros2/message_filters/pull/84for more information.New upsampling time policyAdds in a new time policy calledLatestTime. +It can synchronize up to 9 messages by their rates with upsampling via zero-order-hold. +Seehttps://github.com/ros2/message_filters/pull/73for more information.rcl_yaml_param_parserSupport for YAML!!strsyntax in parameter filesIt is now possible to force the ROS parameter file parser to interpret a field as a string using the YAML!!strsyntax. +Seehttps://github.com/ros2/rcl/pull/999for more information.rclcppDefault number of threads for multi-threaded executor has been changedIf the user doesn’t specify otherwise, the default number of threads for the multi-threaded executor will be set to the number of CPUs on the machine. +If the underlying OS doesn’t support getting this information, it will be set to 2.Seehttps://github.com/ros2/rclcpp/pull/2032for more information.A warning is now printed when QoS of KEEP_LAST is specified with a depth of 0Specifying a QoS of KEEP_LAST with a depth of 0 is a nonsensical arrangement, since the entity wouldn’t be able to send or receive any data.rclcppwill now print a warning if this combination is specified, but will still continue on and let the underlying middleware choose a sane value (generally a depth of 1).Seehttps://github.com/ros2/rclcpp/pull/2048for more information.DeprecatedRCLCPP_SCOPE_EXITmacro was removedIn Humble, the macroRCLCPP_SCOPE_EXITwas deprecated in favor ofRCPPUTILS_SCOPE_EXIT. +In Iron, theRCLCPP_SCOPE_EXITmacro has been completely removed.rclpyDefault number of threads for multi-threaded executor has been changedIf the user doesn’t specify otherwise, the default number of threads for the multi-threaded executor will be set to the number of CPUs on the machine. +If the underlying OS doesn’t support getting this information, it will be set to 2.Seehttps://github.com/ros2/rclpy/pull/1031for more information.A warning is now printed when QoS of KEEP_LAST is specified with a depth of 0Specifying a QoS of KEEP_LAST with a depth of 0 is a nonsensical arrangement, since the entity wouldn’t be able to send or receive any data.rclpywill now print a warning if this combination is specified, but will still continue on and let the underlying middleware choose a sane value (generally a depth of 1).Seehttps://github.com/ros2/rclpy/pull/1048for more information.Time and Duration no longer raise exception when compared to another typeIt is now possible to comparerclpy.time.Timeandrclpy.duration.Durationto other types without getting exceptions. +If the types are not comparable, the comparison returnsFalse. +Note that this is a behavior change from previous releases.print(Nonein[rclpy.time.Time(),rclpy.duration.Duration()])# Prints "False" instead of raising TypeErrorSeehttps://github.com/ros2/rclpy/pull/1007for more information.rcutilsImprove the performance of message loggingThe code used to output a log message whenRCUTILS_LOG_*orRCLCPP_*was optimized to reduce overhead. +These log messages should now be more efficient, though they should still not be called at high rates. +Seehttps://github.com/ros2/rcutils/pull/381,https://github.com/ros2/rcutils/pull/372,https://github.com/ros2/rcutils/pull/369, andhttps://github.com/ros2/rcutils/pull/367for more information.Deprecatedrcutils/get_env.hheader was removedIn Humble, the headerrcutils/get_env.hwas deprecated in favor ofrcutils/env.h. +In Iron, thercutils/get_env.hheader been completely removed.rmwChange the GID storage to 16 bytesThe GID in the RMW layer is meant to be a globally unique identifier for writers in the ROS graph. +Previously, this was erroneously set to 24 bytes based on a bug in an old RMW implementation. +But thermwpackage should define this, and all of the implementations should conform to that. +Thus, this release defines it as 16 bytes (the DDS standard), and changes all implementations to use that definition.Seehttps://github.com/ros2/rmw/pull/345and the (closed, but relevant)https://github.com/ros2/rmw/pull/328for more information.rmw_dds_commonChange the GID storage to 16 bytesAlong with the change in thermwlayer, change the message that sends out GID information to 16 bytes.Seehttps://github.com/ros2/rmw_dds_common/pull/68for more information.ros2topicros2topichz/bw/pubnow respectuse_sim_timeWhen running under simulation, the ROS 2 ecosystem generally gets its time from a/clocktopic published by the simulator (rather than using the system clock). +ROS 2 nodes are typically informed of this change by setting theuse_sim_timeparameter on the node. +The node created by theros2topiccommandshz,bw, andpubnow respect that parameter and will use simulation time as appropriate.Seehttps://github.com/ros2/ros2cli/pull/754for more information.rosbag2Change default bag file type tomcapPrior to this release, by default rosbag2 would record data into sqlite3 databases. +During testing, it was found that in many cases this was not performant enough and lacked certain features desirable for offline processing.To meet these needs, a new bag format (influenced by the original ROS 1 bag file format) calledmcapwas developed. +This bag file format has many of the missing features from the sqlite3 file format, and should also be more performant.This release switches to usingmcapas the default file format for writing new bags. +The oldsqlite3file format is still available and can be selected by the user for writing if desired. +This release also allows playing back data from either thesqlite3file format or themcapfile format.Seehttps://github.com/ros2/rosbag2/pull/1160for more information.Store message definitions in bag files with SQLite3 pluginNow we support saving message definitions to thesqlite3database file in the same format +as we are saving it to themcapfile. +This opens an opportunity for third-party tools to have +the ability to deserialize rosbag2 files without having the correct version of all the original +.msg files on the machine that is decoding the bag file recorded withsqlite3plugin.Seehttps://github.com/ros2/rosbag2/issues/782andhttps://github.com/ros2/rosbag2/pull/1293for +more information.New playback and recording controlsSeveral pull requests have been added to enhance the user’s control over playback of bags. +Pull request960adds the ability to play bag for +a specified number of seconds. +And pull request1005allows to play bag until specified timestamp. +Another pull request1007adds the ability to +stop playback remotely via service call. +Stop will unpause player if it was in pause mode, stop playback and force exit from play() method if it was in progress.Managing recording via service callsThere are new options to control the recording process from remote nodes. +The pull request1131adds the ability to pause and +resume recording via service calls. +Another pull request1115adds the ability to split +bags during recording by sending service call.Filtering topics via regular expression during playbackUsers sometimes need to replay only a subset of topics from recorded bags and the following two pull request +adds such capability. +Pull request1034adds a new option--topics-regexthat allows filtering topics via regular expressions. +The--topics-regexoption accepts multiple regular expressions separated by space. +And pull request1046adds the ability to exclude some +certain topics from being replayed by providing regular expression in a new--exclude(and-x) option.Allow plugins to register their own CLI verb argumentsPull request1209adds the ability forrosbag2plugins to +register an optional Python entrypoint providing plugin-specific CLI argument values. +As a result the command line option--storage-preset-profileforros2bagrecordverb will have +different valid options depending on the underlying storage plugin.Other changesThe pull request1038adds the ability to record +any key/value pair in ‘custom’ field in metadata.yaml file. +It is useful when users need to save some hardware specific id or coordinates where the recording was captured. +And pull request1180adds an option to change the underlying +node name for the recorder via providing the new command line--node-nameoption. +This option might be used for creating remote distributed recording with multiple rosbag2 recorder instances. +It provides the ability to send service calls for managing the recording process to the dedicated +rosbag2 recorder instances.rosidl_pythonModification of content of__slots__attributeSo far, the attribute__slots__from the python message classes, have been used as the member that contains the field names of the message. +In Iron, this attribute no longer contains only the field names from the message structure, but the field names for all the class members. +Therefore, users shouldn’t rely on this attribute to retrieve the field names information, instead, users should retrieve it using the methodget_field_and_field_types().Seehttps://github.com/ros2/rosidl_python/pull/194for more information.rvizMap display can now be shown as binaryThe RViz map display can now display the map as binary, with a settable threshold. +This is useful in some cases to inspect maps or in combination with planners that have a settable threshold.Seehttps://github.com/ros2/rviz/pull/846for more information.Camera display plugin respects the ROI in the CameraInfo messageThe CameraDisplay plugin now honors the region-of-interest (ROI) settings in the CameraInfo message, if it is provided. +This accounts for the fact that an image was cropped by the camera driver to reduce the bandwidth.Seehttps://github.com/ros2/rviz/pull/864for more information.Binary STL files from SOLIDWORKS work without errorA change was made to the STL loader such that it accepts binary STL files from SOLIDWORKS that have the word “solid” in them. +This technically violates the STL specification, but is common enough that a special case is added to handle these files.Seehttps://github.com/ros2/rviz/pull/917for more information.tracetoolsTracing instrumentation is now included by default on LinuxThe ROS 2 core has had tracing instrumentation for a while now. +However, it was compiled out by default. +To get the instrumentation, the LTTng tracer had to be manually installed before rebuilding ROS 2 from source. +In Iron, the tracing instrumentation and tracepoints are included by default; the LTTng tracer is therefore now a ROS 2 dependency.Note that this only applies to Linux.Seehttps://github.com/ros2/ros2_tracing/pull/31andhttps://github.com/ros2/ros2/issues/1177for more information. +Seethis how-to guide to remove the instrumentation (or add the instrumentation with Humble and older).New tracepoints forrclcppintra-process are addedNew tracepoints have been added to supportrclcppintra-process communication. +This allows the evaluation of the time between the message publishing and the callback start in intra-process communication.Seehttps://github.com/ros2/ros2_tracing/pull/30andhttps://github.com/ros2/rclcpp/pull/2091for more information.Known Issuesrmw_connextddsdoes not work with Windows Binary release packages. +RTI is not longer distributingRTIConnextDDS6.0.1which was used by the packaging jobs to create the binaries for Windows. +Instead they now distributeRTIConnextDDS6.1.0which is ABI incompatible with the generated binaries. +The solution is to rely on source builds of ROS 2 andrmw_connextddson Windows.sros2on Windows requires users to downgrade thecryptographypython module tocryptography==38.0.4as discussedhere.ros1_bridgedoes not work with ROS Noetic packages fromupstream Ubuntu. The suggested workaround is to build ROS Noetic from sources, then build theros1_bridgeusing that.Release TimelineNovember, 2022 - Platform decisionsREP 2000 is updated with the target platforms and major dependency versions.By January, 2023 - Rolling platform shiftBuild farm is updated with the new platform versions and dependency versions for Iron Irwini (if necessary).Mon. April 10, 2023 - Alpha + RMW freezePreliminary testing and stabilization of ROS Base[1]packages, and API and feature freeze for RMW provider packages.Mon. April 17, 2023 - FreezeAPI and feature freeze for ROS Base[1]packages in Rolling Ridley. +Only bug fix releases should be made after this point. +New packages can be released independently.Mon. April 24, 2023 - BranchBranch from Rolling Ridley.rosdistrois reopened for Rolling PRs for ROS Base[1]packages. +Iron development shifts fromros-rolling-*packages toros-iron-*packages.Mon. May 1, 2023 - BetaUpdated releases of ROS Desktop[2]packages available. +Call for general testing.Mon. May 15, 2023 - Release CandidateRelease Candidate packages are built. +Updated releases of ROS Desktop[2]packages available.Thu. May 18, 2023 - Distro FreezeFreeze rosdistro. +No PRs for Iron on therosdistrorepo will be merged (reopens after the release announcement).Tue. May 23, 2023 - General AvailabilityRelease announcement.rosdistrois reopened for Iron PRs.[1](1,2,3)Theros_basevariant is described inREP 2001 (ros-base).[2](1,2)Thedesktopvariant is described inREP 2001 (desktop-variants).Development progressFor progress on the development and release of Iron Irwini, seethe tracking GitHub issue.For the broad process followed by Iron Irwini, see theprocess description page. + +Code Examples: + +Language: unknown +voiddo_thing(rclcpp::node_interfaces::NodeGraphInterfacegraph){fprintf(stderr,"Doing a thing\n");}voiddo_thing(rclcpp::Node::SharedPtrnode){do_thing(node->get_node_graph_interface());}voiddo_thing(rclcpp::LifecycleNode::SharedPtrnode){do_thing(node->get_node_graph_interface());} + +Language: unknown +#includeusingrclcpp::experimental::executors::EventsExecutor;EventsExecutorexecutor;executor.add_node(node);executor.spin(); + +Language: unknown +node.wait_for_node('/fully_qualified_node_name') + +Language: unknown +defmsg_info_cb(msg,msg_info):print('Message info:',msg_info)node.create_subscription(msg_type=std_msgs.msg.String,topic='/chatter',qos_profile=10,callback=msg_info_cb) + +Language: unknown +importosfromstd_msgs.msgimportStringos.environ['ROS_PYTHON_CHECK_FIELDS']='1'new_message=String() + +Language: unknown +fromstd_msgs.msgimportStringnew_message=String(check_fields=True) + +Language: unknown +print(Nonein[rclpy.time.Time(),rclpy.duration.Duration()])# Prints "False" instead of raising TypeError diff --git "a/exported_docs/ros2/Iron_Irwini_Changelog\357\203\201.txt" "b/exported_docs/ros2/Iron_Irwini_Changelog\357\203\201.txt" new file mode 100644 index 0000000..83d4c34 --- /dev/null +++ "b/exported_docs/ros2/Iron_Irwini_Changelog\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Iron Irwini Changelog +URL: https://docs.ros.org/en/jazzy/Releases/Iron-Irwini-Complete-Changelog.html +Section: Installation +-------------------------------------------------------------------------------- + +Iron Irwini ChangelogThis page is a list of the complete changes in all ROS 2 core packages since the previous release.Table of Contentsaction_msgsaction_tutorials_cppaction_tutorials_interfacesaction_tutorials_pyactionlib_msgsament_clang_formatament_clang_tidyament_cmakeament_cmake_autoament_cmake_clang_formatament_cmake_clang_tidyament_cmake_copyrightament_cmake_coreament_cmake_cppcheckament_cmake_cpplintament_cmake_export_definitionsament_cmake_export_dependenciesament_cmake_export_include_directoriesament_cmake_export_interfacesament_cmake_export_librariesament_cmake_export_link_flagsament_cmake_export_targetsament_cmake_flake8ament_cmake_gen_version_hament_cmake_gmockament_cmake_google_benchmarkament_cmake_gtestament_cmake_include_directoriesament_cmake_librariesament_cmake_lint_cmakeament_cmake_mypyament_cmake_pclintament_cmake_pep257ament_cmake_pycodestyleament_cmake_pyflakesament_cmake_pytestament_cmake_pythonament_cmake_rosament_cmake_target_dependenciesament_cmake_testament_cmake_uncrustifyament_cmake_vendor_packageament_cmake_versionament_cmake_xmllintament_copyrightament_cppcheckament_cpplintament_flake8ament_index_cppament_index_pythonament_lintament_lint_autoament_lint_cmakeament_lint_commonament_mypyament_packageament_pclintament_pep257ament_pycodestyleament_pyflakesament_uncrustifyament_xmllintbuiltin_interfacescamera_calibration_parserscamera_info_managerclass_loadercommon_interfacescompositioncomposition_interfacesdemo_nodes_cppdemo_nodes_cpp_nativedemo_nodes_pydiagnostic_msgsdomain_coordinatordummy_map_serverdummy_robot_bringupdummy_sensorseigen3_cmake_moduleexample_interfacesexamples_rclcpp_async_clientexamples_rclcpp_cbg_executorexamples_rclcpp_minimal_action_clientexamples_rclcpp_minimal_action_serverexamples_rclcpp_minimal_clientexamples_rclcpp_minimal_compositionexamples_rclcpp_minimal_publisherexamples_rclcpp_minimal_serviceexamples_rclcpp_minimal_subscriberexamples_rclcpp_minimal_timerexamples_rclcpp_multithreaded_executorexamples_rclcpp_wait_setexamples_rclpy_executorsexamples_rclpy_guard_conditionsexamples_rclpy_minimal_action_clientexamples_rclpy_minimal_action_serverexamples_rclpy_minimal_clientexamples_rclpy_minimal_publisherexamples_rclpy_minimal_serviceexamples_rclpy_minimal_subscriberexamples_rclpy_pointcloud_publisherexamples_tf2_pyfastrtps_cmake_modulefoonathan_memory_vendorgeometry2geometry_msgsgoogle_benchmark_vendorignition_cmake2_vendorignition_math6_vendorimage_toolsimage_transportinteractive_markersintra_process_demokdl_parserkeyboard_handlerlaser_geometrylaunchlaunch_pytestlaunch_roslaunch_testinglaunch_testing_ament_cmakelaunch_testing_exampleslaunch_testing_roslaunch_xmllaunch_yamllibcurl_vendorlibstatistics_collectorlibyaml_vendorlifecyclelifecycle_msgslifecycle_pylogging_demomap_msgsmcap_vendormessage_filtersmimick_vendornav_msgsorocos_kdl_vendorosrf_pycommonosrf_testing_tools_cpppendulum_controlpendulum_msgsperformance_test_fixturepluginlibpybind11_vendorpython_cmake_modulepython_orocos_kdl_vendorpython_qt_bindingqt_dotgraphqt_guiqt_gui_appqt_gui_coreqt_gui_cppqt_gui_py_commonquality_of_service_demo_cppquality_of_service_demo_pyrclrcl_actionrcl_interfacesrcl_lifecyclercl_logging_interfacercl_logging_nooprcl_logging_spdlogrcl_yaml_param_parserrclcpprclcpp_actionrclcpp_componentsrclcpp_lifecyclerclpyrcpputilsrcutilsrmwrmw_connextddsrmw_connextdds_commonrmw_connextddsmicrormw_cyclonedds_cpprmw_dds_commonrmw_fastrtps_cpprmw_fastrtps_dynamic_cpprmw_fastrtps_shared_cpprmw_implementationrmw_implementation_cmakerobot_state_publisherros2actionros2bagros2cliros2cli_common_extensionsros2cli_test_interfacesros2componentros2doctorros2interfaceros2launchros2lifecycleros2lifecycle_test_fixturesros2multicastros2noderos2paramros2pkgros2runros2serviceros2testros2topicros2traceros_testingrosbag2rosbag2_compressionrosbag2_compression_zstdrosbag2_cpprosbag2_examples_cpprosbag2_examples_pyrosbag2_interfacesrosbag2_performance_benchmarkingrosbag2_performance_benchmarking_msgsrosbag2_pyrosbag2_storagerosbag2_storage_default_pluginsrosbag2_storage_mcaprosbag2_storage_sqlite3rosbag2_test_commonrosbag2_test_msgdefsrosbag2_testsrosbag2_transportrosgraph_msgsrosidl_adapterrosidl_clirosidl_cmakerosidl_core_generatorsrosidl_core_runtimerosidl_default_generatorsrosidl_default_runtimerosidl_dynamic_typesupportrosidl_dynamic_typesupport_fastrtpsrosidl_generator_crosidl_generator_cpprosidl_generator_dds_idlrosidl_generator_pyrosidl_generator_testsrosidl_generator_type_descriptionrosidl_parserrosidl_pycommonrosidl_runtime_crosidl_runtime_cpprosidl_runtime_pyrosidl_typesupport_crosidl_typesupport_cpprosidl_typesupport_fastrtps_crosidl_typesupport_fastrtps_cpprosidl_typesupport_interfacerosidl_typesupport_introspection_crosidl_typesupport_introspection_cpprosidl_typesupport_introspection_testsrosidl_typesupport_testsrpyutilsrqtrqt_actionrqt_bagrqt_bag_pluginsrqt_consolerqt_graphrqt_guirqt_gui_cpprqt_gui_pyrqt_msgrqt_plotrqt_publisherrqt_py_commonrqt_py_consolerqt_reconfigurerqt_service_callerrqt_shellrqt_srvrqt_topicrti_connext_dds_cmake_modulerttestrviz2rviz_assimp_vendorrviz_commonrviz_default_pluginsrviz_ogre_vendorrviz_renderingrviz_rendering_testsrviz_visual_testing_frameworksensor_msgssensor_msgs_pyservice_msgsshape_msgsshared_queues_vendorspdlog_vendorsqlite3_vendorsros2statistics_msgsstd_msgsstd_srvsstereo_msgstango_icons_vendortest_clitest_cli_remappingtest_communicationtest_interface_filestest_launch_rostest_launch_testingtest_msgstest_osrf_testing_tools_cpptest_quality_of_servicetest_rclcpptest_rmw_implementationtest_ros2tracetest_securitytest_tf2test_tracetoolstest_tracetools_launchtf2tf2_bullettf2_eigentf2_eigen_kdltf2_geometry_msgstf2_kdltf2_msgstf2_pytf2_rostf2_ros_pytf2_sensor_msgstf2_toolstlsftlsf_cpptopic_monitortopic_statistics_demotracetoolstracetools_launchtracetools_tracetrajectory_msgsturtlesimtype_description_interfacesunique_identifier_msgsurdfurdf_parser_pluginvisualization_msgsyaml_cpp_vendorzstd_vendoraction_msgsUpdate common_interfaces to C++17. (#215) (#151)Add service_msgs package (#143)[rolling] Update maintainers - 2022-11-07 (#150)Depend on rosidl_core_generators for packages required by actions (#144)Contributors: Audrow Nash, Brian, Chris Lalancette, Jacob Perronaction_tutorials_cppChange all ROS2 -> ROS 2. (#610)Update the demos to C++17. (#594)Add README’s for action_tutorials. (#576)[rolling] Update maintainers - 2022-11-07 (#589)Fix two small bugs in the fibonacci C++ tutorial. (#564)Contributors: Audrow Nash, Chris Lalancette, kagibsonaction_tutorials_interfacesChange all ROS2 -> ROS 2. (#610)A couple more upgrades to C++17. (#609)Add README’s for action_tutorials. (#576)[rolling] Update maintainers - 2022-11-07 (#589)Remove action_msgs dependency (#580)Contributors: Audrow Nash, Chris Lalancette, Jacob Perron, kagibsonaction_tutorials_pyAdd README’s for action_tutorials. (#576)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, kagibsonactionlib_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancetteament_clang_formatament_clang_format: use open braces for enum definitions (#426)[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, james-rms, methylDragonament_clang_tidy[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)recommend use of –mixin compile-commands (#371)Improve message and avoid missing new lines between reports from files (#373)Contributors: Audrow Nash, William Woodall, methylDragonament_cmake[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_autoSupport INTERFACE on ament_auto_add_library (#420)Fix ament_auto_add_gtest’s parameter passing (#421)[rolling] Update maintainers - 2022-11-07 (#411)Rolling: ament_cmake_auto should include dependencies as SYSTEM (#385)Contributors: Audrow Nash, Christopher Wecht, Joshua Whitley, Rin Iwaiament_cmake_clang_format[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_clang_tidy[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_copyright[rolling] Update maintainers - 2022-11-07 (#421)[ament_lint_auto] General file exclusion with AMENT_LINT_AUTO_FILE_EXCLUDE (#386)Update maintainers (#379)Contributors: Abrar Rahman Protyasha, Audrow Nash, methylDragonament_cmake_coreament_cmake_uninstall_target: Correct location of install_manifest.txt (#432)Use file(GENERATE OUTPUT) to create dsv files (#416) Using file(WRITE) and file(APPEND) causes the modification stamp of the file to be changed each time CMake configures, resluting in an ‘Installing’ message rather than an ‘Up-to-date’ message even though the file content is identical. Using file(GENERATE OUTPUT) updates the timestamp of the file only if the content changes.Warn when trying to symlink install an INTERFACE_LIBRARY (#417)Workaround to exclude Clion’s cmake folders from colcon test (#410) - Add AMENT_IGNORE to CMAKE_BINARY_DIR to avoid picking up cmake specific folders created by CLion incolconbuildandcolcontestcommandsif (NOT ${UNDEFINED_VAR}) gets evaluated to false, so change to if (NOT UNDEFINED_VAR) so it evaluates to true. (#407)[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoImplement ament_add_default_options (#390)Contributors: Audrow Nash, Kenji Brameld, Michael Orlov, Scott K Logan, Shane Loretz, Silvio Traversaro, methylDragonament_cmake_cppcheck[rolling] Update maintainers - 2022-11-07 (#421)[ament_lint_auto] General file exclusion with AMENT_LINT_AUTO_FILE_EXCLUDE (#386)Update maintainers (#379)Contributors: Abrar Rahman Protyasha, Audrow Nash, methylDragonament_cmake_cpplint[rolling] Update maintainers - 2022-11-07 (#421)[ament_lint_auto] General file exclusion with AMENT_LINT_AUTO_FILE_EXCLUDE (#386)Update maintainers (#379)Contributors: Abrar Rahman Protyasha, Audrow Nash, methylDragonament_cmake_export_definitions[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_export_dependencies[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_export_include_directories[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_export_interfaces[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_export_libraries[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_export_link_flags[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_export_targets[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoSupport new target export template introduced with CMake 3.24 (#395)Fix the order in which Export.cmake files are included (#256)Contributors: Audrow Nash, Timo Röhlingament_cmake_flake8Add flake8 linter ignore support (#424)[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Abrar Rahman Protyasha, Audrow Nash, RFRIEDM-Trimble, methylDragonament_cmake_gen_version_hChanged version gte macro to make it MSVC compatible. Fix#433(#434)[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nash, iquaroboticsament_cmake_gmockFix compiler warnings related to gtest/gmock (#408) * Suppress compiler warnings when building gmock definition of implicit copy constructor … is deprecated because it has a user-declared copy assignment operator [-Wdeprecated-copy] * Declare gtest/gmock include dirs as SYSTEM PRIVATE for test targets[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nash, Robert Haschkeament_cmake_google_benchmark[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_gtestFix compiler warnings related to gtest/gmock (#408) * Suppress compiler warnings when building gmock definition of implicit copy constructor … is deprecated because it has a user-declared copy assignment operator [-Wdeprecated-copy] * Declare gtest/gmock include dirs as SYSTEM PRIVATE for test targets[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nash, Robert Haschkeament_cmake_include_directories[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_libraries[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_lint_cmake[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_mypy[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_pclint[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_pep257[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_pycodestyle[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_pyflakes[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cmake_pytestFix test skipping logic for missing pytest module (#441)Add missing buildtool_depend on python3-pytest (#440)ament_cmake_pytest needs a buildtool_depend on ament_cmake_test. (#439)Fix pytest-cov version detection with pytest >=7.0.0 (#436)use the error handler replace to allow non-utf8 to be decoded (#381)[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoAdd NOCAPTURE option to ament_add_pytest_test (#393)Contributors: Audrow Nash, Chris Lalancette, Christophe Bedard, El Jawad Alaa, Jacob Perron, Scott K Loganament_cmake_pythonSupport Debian-specific install dir for ament_cmake_python (#431)[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoDocument ament_cmake_python (#387)Contributors: Audrow Nash, Shane Loretz, Timo Röhlingament_cmake_ros[rolling] Update maintainers - 2022-11-07 (#16)Update maintainers (#15)Contributors: Audrow Nash, methylDragonament_cmake_target_dependencies[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_testuse the error handler replace to allow non-utf8 to be decoded (#381)[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nash, El Jawad Alaaament_cmake_uncrustify[rolling] Update maintainers - 2022-11-07 (#421)[ament_lint_auto] General file exclusion with AMENT_LINT_AUTO_FILE_EXCLUDE (#386)Update maintainers (#379)Contributors: Abrar Rahman Protyasha, Audrow Nash, methylDragonament_cmake_vendor_packageFix the version number of ament_cmake_vendor_package.Add ament_cmake_vendor_package package (#429)Contributors: Chris Lalancette, Scott K Loganament_cmake_version[rolling] Update maintainers - 2022-11-07 (#411) * Update maintainers to Michael JeronimoContributors: Audrow Nashament_cmake_xmllint[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_copyright[rolling] Update maintainers - 2022-11-07 (#421)Support for matching license header within multiline comment block (#361)Improved licencse matching (#358)Updated regex and adding test cases for copyright search (#363)Update maintainers (#379)Contributors: Audrow Nash, Will, methylDragonament_cppcheck[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_cpplint[rolling] Update maintainers - 2022-11-07 (#421)[ament_cpplint] Process errors without linenums (#385)Update maintainers (#379)Consider files with ‘.hh’ extension as C++ headers (#374)Contributors: Abrar Rahman Protyasha, Audrow Nash, Jacob Perron, methylDragonament_flake8[rolling] Update maintainers - 2022-11-07 (#421)Fix exclude regression (#387)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_index_cpp[rolling] Update maintainers - 2022-11-07 (#89)Contributors: Audrow Nashament_index_python[rolling] Update maintainers - 2022-11-07 (#89)Contributors: Audrow Nashament_lint[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_lint_autoAdd flake8 linter ignore support (#424)[rolling] Update maintainers - 2022-11-07 (#421)[ament_lint_auto] General file exclusion with AMENT_LINT_AUTO_FILE_EXCLUDE (#386)Update maintainers (#379)Contributors: Abrar Rahman Protyasha, Audrow Nash, RFRIEDM-Trimble, methylDragonament_lint_cmake[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_lint_common[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_mypy[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_packageAdd support for comment lines in dsv files (#139)[rolling] Update maintainers - 2022-11-07 (#138)Mirror rolling to masterRemove unused isolated prefix level templates (#133)Contributors: Audrow Nash, Scott K Logan, Shane Loretzament_pclint[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_pep257updating ref to pep257 docs (#433)Added underscore to ignore new pydocstyle item (#428)[rolling] Update maintainers - 2022-11-07 (#421)[ament_pep257][master] redirecting error prints to stderr (#390)Update maintainers (#379)Contributors: Audrow Nash, Christian Henkel, Cristóbal Arroyo, Mirco Colosi (CR/AAS3), methylDragonament_pycodestyleament_pycodestyle - fix crash caused by reporting on ignored errors (#435)[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, Shane Loretz, methylDragonament_pyflakes[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_uncrustify[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonament_xmllint[rolling] Update maintainers - 2022-11-07 (#421)Update maintainers (#379)Contributors: Audrow Nash, methylDragonbuiltin_interfacesUpdate common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)Depend on rosidl_core_generators for packages required by actions (#144)Fix documented range (#139)Contributors: Audrow Nash, Chris Lalancette, Jacob Perron, Tully Footecamera_calibration_parsersUpdate image_common to C++17. (#267)Add alias library targets for all libraries (#259)Add support for missing ROI and binning fields (#254)Contributors: AndreasR30, Chris Lalancette, RFRIEDM-Trimblecamera_info_managerUpdate image_common to C++17. (#267)Add alias library targets for all libraries (#259)Add lifecycle node compatibility to camera_info_manager (#190)Contributors: Chris Lalancette, RFRIEDM-Trimble, Ramon Wijnandsclass_loadermake sanitizer happy (#205)[rolling] Update maintainers - 2022-11-07 (#206)Remove appveyor configuration. (#204)Just fix a typo in a comment. (#203)make the meta-object alive in the lifecycle of the registered plugin (#201)Mirror rolling to ros2Contributors: Audrow Nash, Chen Lihui, Chris Lalancettecommon_interfaces[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow NashcompositionChange all ROS2 -> ROS 2. (#610)update launch file name format to match documentation (#588)Added README.md for composition (#598)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)fix memory leak (#585)Contributors: Audrow Nash, Chen Lihui, Chris Lalancette, Gary Bey, Patrick Wspanialycomposition_interfacesUpdate common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)Contributors: Audrow Nash, Chris Lalancettedemo_nodes_cppChange all ROS2 -> ROS 2. (#610)Add matched event demo for rclcpp and rclpy (#607)Fix the set_parameters_callback example program. (#608)[demo_nodes_cpp] Add YAML launch demos for topics (#605)update launch file name format to match documentation (#588)Service introspection (#602) * Add in a rclcpp and rclpy demo of introspection.Added README.md for demo_cpp_nodes (#599)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Demo for pre and post set parameter callback support (#565) * local parameter callback supportcounter starts from 1, not 2. (#562)add a demo of content filter listener (#557)Contributors: Audrow Nash, Barry Xu, Chen Lihui, Chris Lalancette, Damien LaRocque, Deepanshu Bansal, Gary Bey, Patrick Wspanialy, Tomoya Fujitademo_nodes_cpp_nativeChange all ROS2 -> ROS 2. (#610)Added README.md for demo_cpp_nodes_native (#597)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Make demo_nodes_cpp_native install stuff only when it builds (#590)Contributors: Audrow Nash, Chris Lalancette, Gary Bey, Shane Loretzdemo_nodes_pyChange all ROS2 -> ROS 2. (#610)Add matched event demo for rclcpp and rclpy (#607)Enable document generation using rosdoc2 (#606)Service introspection (#602)Added README.md for demo_nodes_py (#600)[rolling] Update maintainers - 2022-11-07 (#589)Demo for pre and post set parameter callback support (#565)Add demo for rclpy parameter client (#566)Exit with code 0 if ExternalShutdownException is raised (#581)Contributors: Audrow Nash, Barry Xu, Brian, Chris Lalancette, Deepanshu Bansal, Gary Bey, Jacob Perron, Yadudiagnostic_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancettedomain_coordinator[rolling] Update maintainers - 2022-11-07 (#16)Update maintainers (#15)Contributors: Audrow Nash, methylDragondummy_map_serverChange all ROS2 -> ROS 2. (#610)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Added README.md for dummy_map_server (#572)Contributors: Audrow Nash, Chris Lalancette, Gary Beydummy_robot_bringupupdate launch file name format to match documentation (#588)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Patrick Wspanialydummy_sensorsFix unstable LaserScan status for rviz2 (#616)Added README.md for dummy_sensors (#573)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chen Lihui, Chris Lalancette, Gary Beyeigen3_cmake_module[rolling] Update maintainers - 2022-11-07 (#6)Mirror rolling to masterUpdate maintainers (#4)Contributors: Audrow Nash, methylDragonexample_interfaces[rolling] Update maintainers - 2022-11-07 (#17)Remove action_msgs dependency (#16)Mirror rolling to masterContributors: Audrow Nash, Jacob Perronexamples_rclcpp_async_clientUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_cbg_executorUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_action_clientUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_action_serverUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_clientUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_compositionUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_publisherUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_serviceUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_minimal_subscriberUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)add ContentFilteredTopic example. (#341)Contributors: Audrow Nash, Chris Lalancette, Tomoya Fujitaexamples_rclcpp_minimal_timerUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_multithreaded_executorUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Chris Lalancetteexamples_rclcpp_wait_setUpdate the examples to C++17. (#353)[rolling] Update maintainers - 2022-11-07 (#352)Add test linting to wait_set and fix issues. (#346) (#347)Contributors: Audrow Nash, Chris Lalancette, mergify[bot]examples_rclpy_executors[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_guard_conditions[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_minimal_action_clientEnable document generation using rosdoc2 for ament_python pkgs (#357) * Add missing action_msgs dep * Add exec_deps for launch_testing_examples[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nash, Yaduexamples_rclpy_minimal_action_server[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_minimal_client[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_minimal_publisher[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_minimal_service[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_minimal_subscriber[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_rclpy_pointcloud_publisher[rolling] Update maintainers - 2022-11-07 (#352)Contributors: Audrow Nashexamples_tf2_pyEnable document generation using rosdoc2 for ament_python pkgs (#587)Update maintainers (#560)Contributors: Audrow Nash, Yadufastrtps_cmake_module[rolling] Update maintainers - 2022-11-07 (#93)Contributors: Audrow Nashfoonathan_memory_vendorAdded support for QNX 7.1 build (#65)Update upstream to release 0.7-3 (#62)(#63)Fix CMake minimum required version (#60)geometry2Update maintainers (#560)Contributors: Audrow Nashgeometry_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancettegoogle_benchmark_vendorActually update to 1.6.1. (#25) We claimed we were, but in fact we were pinned to the 1.5.3 git hash.Remove set but unused variable (#24) Clang checks -Wunused-but-set-variable. This fails the build with -Werror also enabled.[rolling] Update maintainers - 2022-11-07 (#22)Mirror rolling to mainContributors: Audrow Nash, Chris Lalancette, Michael Carrollignition_cmake2_vendorSet target version to 2.14.0 (#5)Mirror rolling to mainContributors: Audrow Nash, Yaduignition_math6_vendorForward CMAKE_PREFIX_PATH when building vendor package (#8)Contributors: Scott K Loganimage_toolsAdded README.md for image_tools - [Clean] (#596)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris Lalancette, Gary Beyimage_transportUpdate image_common to C++17. (#267)Add alias library targets for all libraries (#259)Remove subscriber and publisher impl methods without options (#252)Deprecate impl without options (#249)opt-in to qos overriding for publisher (#246)Add qos option to override qos (#208)Contributors: Brian, Chris Lalancette, Daisuke Nishimatsu, Kenji Brameld, RFRIEDM-Trimbleinteractive_markersUpdate interactive_markers to C++17. (#99)Update maintainers (#98)Mirror rolling to ros2update maintainer (#92)Contributors: Audrow Nash, Chris Lalancette, Dharini Dutiaintra_process_demoFix executable name in README (#619)Change all ROS2 -> ROS 2. (#610)Added README.md for intra_process_demo (#595)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris Lalancette, Gary Bey, Yadunundkdl_parserSwitch some tests to use unique pointers instead of raw pointers. (#74)log link children as DEBUG instead of INFO (#71)Enable the kdl_parser tests in ROS 2 (#68)Add in a LICENSE file and fix up copyright headers (#66)Use orocos_kdl_vendor and orocos-kdl target (#64)Use the rcutils logger instead of printf (#65)Contributors: Chris Lalancette, Joseph Schornak, Scott K Logan, yuraSomatickeyboard_handlerForce exit from main thread on signal handling inkeyboard_handler(#23)Contributors: Michael Orlovlaser_geometryUpdate laser_geometry to C++17. (#90)Update Maintainers (#88)Mirror rolling to ros2Contributors: Audrow Nash, Chris LalancettelaunchDocument LaunchService.{run,run_async}() return value (#702)[rosdoc2] Fix document generation on buildfarm (#701)Enable document generation using rosdoc2 for ament_python pkgs (#697)Remove the import of Literal from entity.py. (#694)Fix flake8 errors. (#695)add symlink to latest log directory (#686)Improve type checking (#679)Fixed typos (#692)Pass modules to PythonExpression (#655)Allow ReadyToTest() usage in event handler (#665)Expose emulate_tty to xml and yaml launch (#669)Expose sigterm_timeout and sigkill_timeout to xml frontend (#667)[rolling] Update maintainers - 2022-11-07 (#671)Expect deprecation warnings in tests (#657)Fix the restoring of os.environ to maintain type. (#656)Implement Any, All, Equals, and NotEquals substitutions (#649)add LaunchLogDir substitution, replacing log_dir frontend only substitution (#652)Add special cases to coerce “1” and “0” to bool when using bool coercion only (#651)Update launch/test/launch/test_execute_local.pyAdded unit test ensuring that output dictionary works with ExecuteLocalAddresses issue#588, allowing dict for ‘output’Remove unused variables. (#612)Expose shutdown action to xml frontend (#611)Contributors: Aditya Pande, Alejandro Hernández Cordero, Audrow Nash, Blake Anderson, Chris Lalancette, Christophe Bedard, Hervé Audren, Jacob Perron, Matthew Elwin, Michael Jeronimo, Nikolai Morin, Welte, William Woodall, Yadu, methylDragonlaunch_pytestFixed typos (#692)Drop unused data_files entry for example_processes (#680)Spelling correction[rolling] Update maintainers - 2022-11-07 (#671)Contributors: Alejandro Hernández Cordero, Audrow Nash, Geoffrey Biggs, Scott K Loganlaunch_rosUse SomeEntitiesType for type checking. (#358)Fix normalize_parameters_dict for multiple nodes in the same namespace (#347)Implement None check for ComposableNodeContainer (#341)Add LifecyleTransition action (#317)Improve evaluate_paramenter_dict exceptions error message (#320)Ensure load_composable_nodes respects condition (#339)fix: return text value to avoid exception (#338)[rolling] Update maintainers - 2022-11-07 (#331)RosTimer -> ROSTimer and PushRosNamespace -> PushROSNamespace, to follow PEP8 (#326)add SetROSLogDir action (#325)Support default values in parameter substitution (#313)Run condition for composable nodes (#311)Contributors: Aditya Pande, Alexey Merzlyakov, Audrow Nash, Chris Lalancette, Christoph Hellmann Santos, Daisuke Nishimatsu, Felipe Gomes de Melo, Kenji Miyake, William Woodall, methylDragonlaunch_testingImprove type checking (#679)Fixed typos (#692)Allow ReadyToTest() usage in event handler (#665)Inherit markers from generate_test_description (#670)[rolling] Update maintainers - 2022-11-07 (#671)Fix Typo (#641)ReadyToTest action timeout using decorator (#625)Switch to using a comprehension for process_names. (#614)Contributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Deepanshu Bansal, Hervé Audren, Kenji Brameld, Nikolai Morin, Scott K Loganlaunch_testing_ament_cmake[rolling] Update maintainers - 2022-11-07 (#671)Contributors: Audrow Nashlaunch_testing_examplesEnable document generation using rosdoc2 for ament_python pkgs (#357)increase the timeout for window platform to avoid flaky test (#355)[rolling] Update maintainers - 2022-11-07 (#352)Increase the WaitForNode timeout. (#350)Contributors: Audrow Nash, Chen Lihui, Chris Lalancette, Yadulaunch_testing_rosIncrease the timeouts in wait_for_topic_launch_test. (#360)Enable document generation using rosdoc2 (#359)exit() methods should not reraise the passed-in exception (#357)Inherit markers from generate_test_description (#330)[rolling] Update maintainers - 2022-11-07 (#331)Fix long wait during shutdown in WaitForTopics (#314)Contributors: Audrow Nash, Chris Lalancette, Giorgio Pintaudi, Keng12, Scott K Logan, Yadulaunch_xmlFixed typos (#692)Expose emulate_tty to xml and yaml launch (#669)Expose sigterm_timeout and sigkill_timeout to xml frontend (#667)[rolling] Update maintainers - 2022-11-07 (#671)Contributors: Aditya Pande, Alejandro Hernández Cordero, Audrow Nashlaunch_yamlExpose emulate_tty to xml and yaml launch (#669)Expose sigterm_timeout and sigkill_timeout to xml frontend (#667)[rolling] Update maintainers - 2022-11-07 (#671)Contributors: Aditya Pande, Audrow Nashlibcurl_vendormerge libcurl_vendor build instructions (#81)Sets CMP0135 policy behavior to NEW (#79)Fixes policy CMP0135 warning for CMake >= 3.24Contributors: Cristóbal Arroyo, Crola1702, schrodinbuglibstatistics_collectorBump hmarr/auto-approve-action from 3.2.0 to 3.2.1Mark benchmark _ as unused. (#158)Bump hmarr/auto-approve-action from 3.1.0 to 3.2.0Bump ros-tooling/action-ros-ci from 0.2 to 0.3Bump pascalgn/automerge-action from 0.15.5 to 0.15.6Update libstatistics_collector to C++17. (#154)Remove unnecessary build dependency on std_msgs. (#145)Bump pascalgn/automerge-action from 0.15.2 to 0.15.3Cleanup the CI jobs on this repository. (#146)Check if message has a “header” field with a stamp subfield of type builtin_interfaces::msg::Time (#54)Mirror rolling to masterContributors: Audrow Nash, Chris Lalancette, Scott Mende, dependabot[bot]libyaml_vendorFix system package dependency (#54)Update libyaml_vendor to C++17. (#55)[rolling] Update maintainers - 2022-11-07 (#53)Remove a warning message. (#51)check if libyaml is already present before building it (take 2) (#45)Mirror rolling to masterSupport WindowsStore builds for ROS2 (#50) * libyaml for uwpContributors: Audrow Nash, Chris Lalancette, Lou Amadio, Scott K Logan, Silvio Traversarolifecycleupdate launch file name format to match documentation (#588)Update the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris Lalancette, Patrick Wspanialylifecycle_msgsUpdate common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)lifecycle_msgs: remove non-ASCII chars from field comments (#147)Contributors: Audrow Nash, Chris Lalancette, G.A. vd. Hoornlifecycle_pyEnable document generation using rosdoc2 (#606)update launch file name format to match documentation (#588)Cleanup lifecycle_py to conform to ROS 2 standards. (#604)[rolling] Update maintainers - 2022-11-07 (#589)Install the launch file for lifecycle_py. (#586)Contributors: Audrow Nash, Chris Lalancette, Patrick Wspanialy, Yadulogging_demoUpdate the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Change dependency from ‘rosidl_cmake’ to ‘rosidl_default_generators’ (#578)Contributors: Audrow Nash, Chris Lalancette, Jacob Perronmap_msgsUpdate maintainersContributors: Audrow Nash, Steve Macenskimcap_vendormcap_vendor: add readme with versioning procedure (#1230)Add Michael Orlov as maintainer in rosbag2 packages (#1215)mcap_vendor: only install public headers (#1207)Fixes policy CMP0135 warning for CMake >= 3.24 for mcap_vendor (#1208)mcap_vendor: download MCAP source via tarball (#1204)rosbag2_cpp: test more than one storage plugin (#1196)rosbag2_storage_mcap: merge into rosbag2 repo (#1163)Fix Windows build (#73) Update mcap version to newest windows-compatible release. Add visibility macros for tests. Add clang-format preprocessor indentation for visibility_control to be readable.mcap_vendor: update to v0.6.0 (#69)Cleanup inmcap_vendorpackage (#62)Switch to using the vendored zstd library. (#59)Support timestamp-ordered playback (#50)Support regex topic filteringAdd all lz4 sources to fix undefined symbols at runtime (#46)Upgrade mcap to fix LZ4 error and segfault (#42) Incorporates fixes fromhttps://github.com/foxglove/mcap/pull/478andhttps://github.com/foxglove/mcap/pull/482Add missing buildtool_depend on git (#37) This vendor package uses git to fetch sources for other packages. It should declare a dependency on that build tool. This should address the current cause of RPM build failures for RHEL:https://build.ros2.org/view/Rbin_rhel_el864/job/Rbin_rhel_el864__mcap_vendor__rhel_8_x86_64__binary/Test Foxy & Galactic in CI, fix missing test_depends in mcap_vendor/package.xml (#33)fix: minor issues (#31) * remove unnecessary block * use target_link_libraries instead of ament_target_dependencies * remove ros environment * add prefix to compile definitionUpdate email address for Foxglove maintainers (#32)Added mcap_vendor package. Updated CMakeLists.txt to fetch dependencies with FetchContent rather than Conan.Contributors: Chris Lalancette, Cristóbal Arroyo, Daisuke Nishimatsu, Emerson Knapp, Jacob Bandes-Storch, James Smith, Michael Orlov, Scott K Logan, james-rmsmessage_filtersUpdate message_filters to C++17. (#88)Fix cache.h std::placeholder namespace (#87)[rolling] Update maintainers - 2022-11-07 (#85)Add a simpler aproximate time sync policy: ApproximateEpsilonTime (#84)Add latest time zero-order-hold sync policy (#73)Fix python examples and add a new example in documentation (#79)Mirror rolling to masterAdding fix to subscribe() call with raw node pointer and subscriber options (#76)Corrected function arguments in example description (#35)Changed invocation toaddto conform template syntax (#1388)fix sphinx warning (#1371)change invocation toaddto conform template syntax (#1388)fix sphinx warning (#1371)Contributors: Audrow Nash, Carlos Andrés Álvarez Restrepo, Chris Lalancette, Haoru Xue, Ivan Santiago Paunovic, Martin Ganeff, Steve Macenski, andermimimick_vendor[rolling] Update maintainers - 2022-11-07 (#29)Mirror rolling to masterContributors: Audrow Nashnav_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancetteorocos_kdl_vendorMake sure to quote orocos variables when setting targets. (#12)Ensure orocos-kdl is available as a target (#10)Ensure orocos-kdl target references Eigen (#6)Contributors: Chris Lalancette, Scott K Loganosrf_pycommon[master] Update maintainers - 2022-11-07 (#89)Declare test dependencies in [test] extra (#86)Contributors: Audrow Nash, Scott K Loganosrf_testing_tools_cppFix mpark/variant conditional for MSVC (#77)Changing C++ Compile Version (#76)Update maintainers (#74)Sets CMP0135 policy behavior to NEW (#73)Fixes policy CMP0135 warning in CMake 3.24 (#71)Add cstring include. (#70)Contributors: Audrow Nash, Chris Lalancette, Cristóbal Arroyo, Lucas Wendland, Scott K Loganpendulum_controlUpdate the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris Lalancettependulum_msgsChange all ROS2 -> ROS 2. (#610)A couple more upgrades to C++17. (#609)Added README.md for pendulum_msgs. (#577)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris Lalancette, Gary Beyperformance_test_fixtureResolve use-after-free compiler warnings (#24)Update performance_test_fixture to C++17. (#21)[rolling] Update maintainers - 2022-11-07 (#20)Mirror rolling to mainAdd “cstring” to the list of includes (#19)Contributors: Audrow Nash, Chris Lalancette, Scott K LoganpluginlibUpdate maintainersContributors: Audrow Nashpybind11_vendorAdd a modified patch from upstream to support Python 3.11 (#22)Add missing buildtool dependency on git (#19)Update maintainers (#17)Force pybind11 to find Python 3. (#15)Mirror rolling to masterUpdate maintainers (#14)Update to pybind11 2.9.1.Rename patch file for history continuity.Contributors: Audrow Nash, Chris Lalancette, Scott K Logan, Steven! Ragnarök, methylDragonpython_cmake_module[rolling] Update maintainers - 2022-11-07 (#13)Mirror rolling to masterContributors: Audrow Nashpython_orocos_kdl_vendorFixes policy CMP0135 warning for CMake >= 3.24 (#16)Workaround pybind11 CMake error (#9)Contributors: Cristóbal Arroyo, Jacob Perronpython_qt_bindingFix to allow ninja to use make for generators (#123)Fix flake8 linter regression (#125)Remove pyqt from default binding order for macOS (#118)Demote missing SIP message from WARNING to STATUS (#122)[rolling] Update maintainers - 2022-11-07 (#120)Contributors: Audrow Nash, Christoph Hellmann Santos, Cristóbal Arroyo, Michael Carroll, Rhys Mainwaring, Scott K Loganqt_dotgraphAdd in LICENSE fileCast drawLine input arguments to int (#264) (#265)Contributors: Chris Lalancette, mergify[bot]qt_guiAdd in LICENSE fileFix flake8 errors introduced by the previous commit. (#262)Enable basic help information if no plugins are running (#261)Contributors: Chris Lalancette, Michael Jeronimoqt_gui_appAdd in LICENSE fileContributors: Chris Lalancetteqt_gui_coreAdd in LICENSE fileContributors: Chris Lalancetteqt_gui_cppFix ClassLoader warning by unloading plugin providers. (#275)Chen Lihuifix shiboken error (#267)Conditionally run import tests when generators are built (#269)Add in LICENSE fileContributors: Chris Lalancette, Christoph Hellmann Santos, Michael Carroll, Rhys Mainwaring, Scott K Loganqt_gui_py_commonAdd in LICENSE fileContributors: Chris Lalancettequality_of_service_demo_cppUpdate the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris Lalancettequality_of_service_demo_pyUse non-deprecated rclpy import. (#617)Change all ROS2 -> ROS 2. (#610)Enable document generation using rosdoc2 (#606)[rolling] Update maintainers - 2022-11-07 (#589)Exit with code 0 if ExternalShutdownException is raised (#581)Contributors: Audrow Nash, Chris Lalancette, Jacob Perron, YadurclHonor ROS_LOCALHOST_ONLY if enabled. (#1071)fix flaky test (#1063)Add enable_type_description_service node option - API only (#1060)Dynamic Subscription (BONUS: Allocators): rcl (#1057)Runtime Interface Reflection: rcl (#1025)[rcl] Improve handling of dynamic discovery (#1023)Use get_type_hash_func for typesupports (#1055)publish for rosout topic multiple times to avoid flaky test (#1054)Switch to target_link_libraries in rcl. (#1051)Calculate type hash from TypeDescription (rep2011) (#1027)Implement matched event (#1033)use user-defined allocator to configure logging. (#1047)user defined allocator should be used for rosout publisher. (#1044)Add in inconsistent_topic implementation. (#1024)doc update, ROS message accessibility depends on RMW implementation. (#1043)Fix some warnings from clang. (#1042)avoid unnecessary copy for rcutils_char_array_vsprintf. (#1035)Service introspection (#997)Cache disable flag to avoid reading environmental variable. (#1029)use parent logger (#921)Add timer on reset callback (#995)Update rcl to C++17. (#1031)Make sure to check the return value of rcl_clock_init in tests. (#1030)Implement rcl_clock_time_started (#1021)Make sure to reset errors more places in the tests. (#1020) This makes it so we don’t get as many warnings when the tests are running.[rolling] Update maintainers - 2022-11-07 (#1017)Small cleanups to rcl (#1013)use int64_t for period. (#1010)fixed rcl_wait return error when timer cancelled (#1003)remove duplicate packages in find_package and reorder (#994)Fix buffer overflow in argument parsing caused by lexer returning length beyond length of string (#979)Fix leak in test_subscription_content_filter_options.cpp (#978)Contributors: Audrow Nash, Barry Xu, Brian, Chen Lihui, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Shane Loretz, Tomoya Fujita, mauropasse, methylDragon, 정찬희rcl_actiondoc update, ROS message accessibility depends on RMW implementation. (#1043)Update rcl to C++17. (#1031)Reduce result_timeout to 10 seconds. (#1012)[rolling] Update maintainers - 2022-11-07 (#1017)Contributors: Audrow Nash, Chris Lalancette, Tomoya Fujitarcl_interfacesAdd interfaces for logging service. (#154)Update common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)Contributors: Audrow Nash, Chris Lalancette, Lei Liurcl_lifecycleUpdate rcl to C++17. (#1031)[rolling] Update maintainers - 2022-11-07 (#1017)Contributors: Audrow Nash, Chris Lalancettercl_logging_interfaceUpdate rcl_logging to C++17. (#98)Updated maintainers - 2022-11-07 (#96)Contributors: Audrow Nash, Chris Lalancettercl_logging_noopUpdate rcl_logging to C++17. (#98)Updated maintainers - 2022-11-07 (#96)Contributors: Audrow Nash, Chris Lalancettercl_logging_spdlogMark the benchmark _ as unused. (#99)Update rcl_logging to C++17. (#98)change flushing behavior for spdlog log files, and add env var to use old style (no explicit flushing) (#95) * now flushes every ERROR message and periodically every 5 seconds * can setRCL_LOGGING_SPDLOG_EXPERIMENTAL_OLD_FLUSHING_BEHAVIOR=1to get old behaviorUpdated maintainers - 2022-11-07 (#96)Disable cppcheck for rcl_logging_spdlog. (#93)ament_export_dependencies any package with targets we linked against (#89)Contributors: Audrow Nash, Chris Lalancette, Shane Loretz, William Woodallrcl_yaml_param_parserFix some warnings from clang. (#1042)Cleanup the dependencies in rcl_yaml_param_parser. (#1014)Update rcl to C++17. (#1031)Support yaml string tag ‘!!str’ (#999)[rolling] Update maintainers - 2022-11-07 (#1017)Contributors: Audrow Nash, Barry Xu, Chris LalancetterclcppFix delivered message kind (#2175) (#2178)Add support for logging service. (#2122)Picking ABI-incompatible executor changes (#2170)add events-executor and timers-manager in rclcpp (#2155)Create common structures for executors to use (#2143)Implement deliver message kind (#2168)applied tracepoints for ring_buffer (#2091)Dynamic Subscription (REP-2011 Subset): Stubs for rclcpp (#2165)Add type_hash to cpp TopicEndpointInfo (#2137)Trigger the intraprocess guard condition with data (#2164)Minor grammar fix (#2149)Fix unnecessary allocations in executor.cpp (#2135)add Logger::get_effective_level(). (#2141)Remove deprecated header (#2139)Implement matched event (#2105)use allocator via init_options argument. (#2129)Fixes to silence some clang warnings. (#2127)Documentation improvements on the executor (#2125)Avoid losing waitable handles while using MultiThreadedExecutor (#2109)Hook up the incompatible type event inside of rclcpp (#2069)Update all rclcpp packages to C++17. (#2121)Fix clang warning: bugprone-use-after-move (#2116)Fix memory leak in tracetools::get_symbol() (#2104)Service introspection (#1985)Allow publishing borrowed messages with intra-process enabled (#2108)to fix flaky test about TestTimeSource.callbacks (#2111)to create a sublogger while getting child of Logger (#1717)Fix documentation of Context class (#2107)fixes for rmw callbacks in qos_event class (#2102)Add support for timers on reset callback (#1979)Topic node guard condition in executor (#2074)Fix bug on the disorder of calling shutdown callback (#2097)Add default constructor to NodeInterfaces (#2094)Fix clock state cached time to be a copy, not a reference. (#2092)Fix -Wmaybe-uninitialized warning (#2081)Fix the keep_last warning when using system defaults. (#2082)Add in a fix for older compilers. (#2075)Implement Unified Node Interface (NodeInterfaces class) (#2041)Do not throw exception if trying to dequeue an empty intra-process buffer (#2061)Move event callback binding to PublisherBase and SubscriptionBase (#2066)Implement validity checks for rclcpp::Clock (#2040)Explicitly set callback type (#2059)Fix logging macros to build with msvc and cpp20 (#2063)Add clock type to node_options (#1982)Fix nullptr dereference in prune_requests_older_than (#2008)Remove templating on to_rcl_subscription_options (#2056)Fix SharedFuture from async_send_request never becoming valid (#2044)Add in a warning for a KeepLast depth of 0. (#2048)Mark rclcpp::Clock::now() as const (#2050)Fix a case that did not throw ParameterUninitializedException (#2036)Update maintainers (#2043)MultiThreadExecutor number of threads is at least 2+ in default. (#2032)Fix bug that a callback not reached (#1640)Set the minimum number of threads of the Multithreaded executor to 2 (#2030)check thread whether joinable before join (#2019)Set cpplint test timeout to 3 minutes (#2022)Make sure to include-what-you-use in the node_interfaces. (#2018)Do not clear entities callbacks on destruction (#2002)fix mismatched issue if using zero_allocate (#1995)Make ParameterService and Sync/AsyncParameterClient accept rclcpp::QoS (#1978)support regex match for parameter client (#1992)operator+= and operator-= for Duration (#1988)Revert “Revert “Add a create_timer method to Node andLifecycleNodeclasses (#1975)” (#2009) (#2010)force compiler warning if callback handles not captured (#2000)Revert “Add acreate_timermethod toNodeandLifecycleNodeclasses (#1975)” (#2009)Add acreate_timermethod toNodeandLifecycleNodeclasses (#1975)[docs] add note about callback lifetime for {on, post}_set_parameter_callback (#1981)fix memory leak (#1994)Support pre-set and post-set parameter callbacks in addition to on-set-parameter-callback. (#1947)Make create_service accept rclcpp::QoS (#1969)Make create_client accept rclcpp::QoS (#1964)Fix the documentation for rclcpp::ok to be accurate. (#1965)use regex for wildcard matching (#1839)Revert “Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (#1821) (#1874)” (#1956)Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (#1821) (#1874)test adjustment for LoanedMessage. (#1951)fix virtual dispatch issues identified by clang-tidy (#1816)Remove unused on_parameters_set_callback_ (#1945)Fix subscription.is_serialized() for callbacks with message info (#1950)wait for subscriptions on another thread. (#1940)Fix documentation ofRCLCPP\_[INFO,WARN,...](#1943)Always trigger guard condition waitset (#1923)Add statistics for handle_loaned_message (#1927)Drop wrong template specialization (#1926)Update get_parameter_from_event to follow the function description (#1922)Add ‘best available’ QoS enum values and methods (#1920)use reinterpret_cast for function pointer conversion. (#1919)Contributors: Alberto Soragna, Alexander Hans, Alexis Paques, Andrew Symington, Audrow Nash, Barry Xu, Brian, Chen Lihui, Chris Lalancette, Christophe Bedard, Christopher Wecht, Cristóbal Arroyo, Daniel Reuter, Deepanshu Bansal, Emerson Knapp, Hubert Liberacki, Ivan Santiago Paunovic, Jacob Perron, Jeffery Hsu, Jochen Sprickerhof, Lei Liu, Mateusz Szczygielski, Michael Carroll, Miguel Company, Nikolai Morin, Shane Loretz, Silvio Traversaro, Tomoya Fujita, Tyler Weaver, William Woodall, Yadu, andrei, mauropasse, mergify[bot], methylDragon, schrodinbug, uupks, ymskirclcpp_actionextract the result response before the callback is issued. (#2132)Update all rclcpp packages to C++17. (#2121)Fix the GoalUUID to_string representation (#1999)Explicitly set callback type (#2059)Update maintainers (#2043)Do not clear entities callbacks on destruction (#2002)Revert “Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (#1821) (#1874)” (#1956)Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (#1821) (#1874)Contributors: Audrow Nash, Chris Lalancette, Hubert Liberacki, Nathan Wiebe Neufeldt, Tomoya Fujita, William Woodall, mauropasserclcpp_componentsUpdate all rclcpp packages to C++17. (#2121)Improve component_manager_isolated shutdown (#2085)Update maintainers (#2043)use unique ptr and remove unuseful container (#2013)Revert “Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (#1821) (#1874)” (#1956)Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (#1821) (#1874)Contributors: Audrow Nash, Chen Lihui, Chris Lalancette, Hubert Liberacki, Michael Carroll, William Woodallrclcpp_lifecycleAdd support for logging service. (#2122)Support publishing loaned messages in LifecyclePublisher (#2159)Fixes to silence some clang warnings. (#2127)Update all rclcpp packages to C++17. (#2121)Use the correct macro for LifecycleNode::get_fully_qualified_name (#2117)add get_fully_qualified_name to rclcpp_lifecycle (#2115)Implement Unified Node Interface (NodeInterfaces class) (#2041)Add clock type to node_options (#1982)Update maintainers (#2043)LifecycleNode on_configure doc fix. (#2034)Bugfix 20210810 get current state (#1756)Make lifecycle impl get_current_state() const. (#2031)Cleanup the lifecycle implementation (#2027)Cleanup the rclcpp_lifecycle dependencies. (#2021)Revert “Revert “Add a create_timer method to Node andLifecycleNodeclasses (#1975)” (#2009) (#2010)Revert “Add acreate_timermethod toNodeandLifecycleNodeclasses (#1975)” (#2009)Add acreate_timermethod toNodeandLifecycleNodeclasses (#1975)Support pre-set and post-set parameter callbacks in addition to on-set-parameter-callback. (#1947)Make create_service accept rclcpp::QoS (#1969)Make create_client accept rclcpp::QoS (#1964)Contributors: Andrew Symington, Audrow Nash, Chris Lalancette, Deepanshu Bansal, Ivan Santiago Paunovic, Jeffery Hsu, Lei Liu, Michael Babenko, Shane Loretz, Steve Macenski, Tomoya Fujita, methylDragonrclpyFix type in Node init args (#1115) (#1122)Logging service support (#1102)Use custom sourcedir for conf.py (#1109)ServerGoalHandle should be destroyed before removing. (#1113)Fix unnecessary list comprehension flake8 (#1112)Stub type hash value line in TopicEndpointInfo string (#1110)Support documentation generation using rosdoc2 (#1103)Fix Time and Duration raising exception when compared to another type (#1007)Make rcl_interfaces a build and exec dependency. (#1100)Solving Atomic undefined on OSX with clang (#1096)Implement matched event (#1083)Update service.py documentation (#1094)Allow space or empty strings when using ros2 param set (#1093)Hook up the incompatible type event inside of rclpy (#1058)Switch to using module instead of module_ (#1090)Add in subscription.get_publisher_count() (#1089)Service introspection (#988)to create a sublogger while getting child of Logger (#1084)Fix#983by saving future and checking for + raising any exceptions (#1073)Force C++17 support on. (#1076)Use RCPPUTILS_SCOPE_EXIT to cleanup unparsed_indices_c. (#1075)Explicitly link atomic when building with Clang (#1065)Fix test_publisher linter for pydocstyle 6.2.2 (#1063)Add default preset qos profile (#1062)Add on_parameter_event method to the AsyncParameterClient. (#1061)Add documentation page for rclpy.clock (#1055)Rewrite test code without depending on parameter client (#1045)Add parallel callback test (#1044)decorator should not be callable. (#1050)typo fix. (#1049)Add in a warning for a depth of 0 with KEEP_LAST. (#1048)Add feature of wait for message (#953). (#960)Document rclpy.time.Time class (#1040)Deal with ParameterUninitializedException for parameter service (#1033)Improve documentation in rclpy.utilities (#1038)Document rclpy.utilities.remove_ros_args (#1036)Fix incorrect comparsion on whether parameter type is NOT_SET (#1032)[rolling] Update maintainers (#1035)Set the default number of threads of the MultiThreadedExecutor to 2 (#1031)Update the rclpy method documentation. (#1026)Revert “Raise user handler exception in MultiThreadedExecutor. (#984)” (#1017)Waitable should check callback_group if it can be executed. (#1001)support wildcard matching for params file (#987)Raise user handler exception in MultiThreadedExecutor. (#984)Add wait_for_node method (#930)Create sublogger for action server and action client (#982)Support for pre-set and post-set parameter callback. (#966)fix gcc 7.5 build errors (#977)make _on_parameter_event return result correctly (#817)Fix a small typo in documentation. (#967)Add Parameter Client (#959)Change sphinx theme to readthedocs (#950)Name and type in descriptor(s) is ignored via declare_parameter(s). (#957)Typo fix (#951)Add py.typed to package (#946)Fix rclpy.shutdown() from hanging when triggered from callback (#947)Check if the context is already shutdown. (#939)Avoid causing infinite loop when message is empty (#935)Expose ‘best available’ QoS policies (#928)remove feedback callback when the goal has been completed. (#927)Allow to create a subscription with a callback that also receives the message info (#922)Contributors: Achille Verheye, Audrow Nash, Barry Xu, Brian, Brian Chen, Chen Lihui, Chris Lalancette, Cristóbal Arroyo, Deepanshu Bansal, Emerson Knapp, Erki Suurjaak, Felix Divo, Florian Vahl, Gonzo, GuiHome, Ivan Santiago Paunovic, Jacob Perron, Lei Liu, Lucas Wendland, Michael Carroll, Sebastian Freitag, Seulbae Kim, Shane Loretz, Steve Nogar, Takeshi Ishita, Tomoya Fujita, Tony Najjar, Yadu, Yuki Igarashi, mergify[bot]rcpputilsAdd missing header for strlen (#169)issue-167 (#172)[rolling] Update maintainers - 2022-11-07 (#166)require C++17 and deprecate the rcppmath namespace (#165)Mirror rolling to masterFix possible race condition in create_directories() (#162)Contributors: Artem Shumov, Audrow Nash, Sebastian Freitag, William Woodall, bijoua29rcutilsfix memory leak (#423)Add convenience error handling macros (#421)Calculate the next power-of-two for the user in hash_map_init. (#420)update cast to modern style (#418)Remove deprecated header get_env.h (#417)Updates to rcutils to make rosdoc2 generation happier. (#416)add RCUTILS_LOGGING_AUTOINIT_WITH_ALLOCATOR. (#415)Fix memory leak in string_map.c in rcutils (#411)avoid unnecessary copy for rcutils_char_array_vsprintf. (#412)Add missing stddef include for size_t (#410)Add SHA256 utility implementation (#408)Upgrade rcutils to C++17. (#392)[rolling] Update maintainers - 2022-11-07 (#404)Fix build on OpenHarmony (#395)regression of thread-safety for logging macros (#393)add portable nonnull macros (#382)Fix memory leak when adding the same key to the logger hash map multiple times (#391)time_unix: uses ZEPHYR_VERSION_CODE instead (#390)Cleanup time_unix.c (#389)time_unix: namespace zephyr headers (#383)Restrict overmatching MACH ifdef to only trigger on OSX and Mach (#386)Optimize rcutils_logging_get_logger_effective_level() (#381)Change syntax __VAR_ARGS__ to __VA_ARGS__ (#376)Fix a bug in hash_map_get_next_key_and_data. (#375)More fixes from review.Fixes from review.Make g_rcutils_logging_output_handler static.Make g_rcutils_logging_default_logger_level static.Optimize rcutils_find_lastn where possible.Don’t bother computing the hash_map key if the hash map is empty.Make sure to expand char_array by at least 1.5x.Optimize index computation in hash_map_find.Improve the performance of rcutils_logging_format_message. (#372)Get rid of unnecessary ret variable.Get rid of unnecessary ifdef cplusplus checks in the C file.Get rid of unnecessary rcutils_custom_add_{gtest,gmock}Get rid of unnecessary and unused RMW switching for logging tests.Remove unnecessary IS_OUTPUT_COLORIZED macro.Rename logging internal structures to use our new convention.Make all of the logging ‘expand’ methods static.Fix up error checking for RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED.Cleanup error handling for the RCUTILS_CONSOLE_OUTPUT_FORMAT checks.Revamp error handling in rcutils_logging_initialize_with_allocator.Revamp rcutils_logging_initialize_with_allocator.Make a few logging global variables static.Optimize calls via the RCUTILS_LOG macros. (#369)time_unix: add zephyr posix time (#368)Optimize the implementation of rcutils_char_array_strncpy. (#367)strdup.c: fix arbitrary length overread (#366)Mirror rolling to masterstrdup.c: fix 1 byte buffer overread (#363)Clarify duration arg description in logging macros (#359)Update rcutils_steady_time_now to return the same data as std::chrono (#357)Contributors: AIxWall, Abrar Rahman Protyasha, Audrow Nash, Chen Lihui, Chris Lalancette, Emerson Knapp, Felipe Neves, Jacob Perron, Mario Prats, Maximilian Downey Twiss, Nikolai Morin, Tomoya Fujita, William Woodall, Yakumoo, guijan, methylDragonrmwDynamic Subscription (BONUS: Allocators): rmw (#353)Runtime Interface Reflection: rmw (#340)[rmw] Improve handling of dynamic discovery (#338)rmw_send_reqponse returns RMW_RET_TIMEOUT. (#350)Add a note about asynchronicity of discovery. (#352)Add matched event support (#331)Add type hash to rmw_topic_endpoint_info_t (rep2011) (#348)Add in inconsistent topic defines and data structures. (#339)Update documented expectations for GIDs (#335)Fix rmw->rwm typo (#347)Add rmw count clients, services (#334)make writer_guid uint8_t[] instead of int8_t for consistency with rmw_gid_t (#329)Update rmw to C++17. (#346)Reduce GID storage to 16 bytes. (#345)Move the RMW_CHECK_TYPE_IDENTIFIERS_MATCH macro to a C header. (#343)[rolling] Update maintainers - 2022-11-07 (#337)Remove unused test_loaned_message_sequence.cpp (#336)callback can be NULL to clear in Listener APIs. (#332)Add rmw_get_gid_for_client method (#327)Add ‘best available’ QoS policies (#320) The best available policy should select the highest level of service for the QoS setting while matching with the majority of endpoints. For example, in the case of a DDS middleware subscription, this means: * Prefer reliable reliability if all existing publishers on the same topic are reliable, otherwise use best effort. * Prefer transient local durability if all existing publishers on the same topic are transient local, otherwise use volatile. * Prefer manual by topic liveliness if all existing publishers on the same topic are manual by topic, otherwise use automatic. * Use a deadline that is equal to the largest deadline of existing publishers on the same topic. * Use a liveliness lease duration that is equal to the largest lease duration of existing publishers on the same topic.Move statuses definitions to rmw/events_statuses/ (#232)Contributors: Audrow Nash, Barry Xu, Brian, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Jacob Perron, Lee, Minju, Nikolai Morin, Tomoya Fujita, William Woodall, methylDragonrmw_connextddsDynamic Subscription (BONUS: Allocators): rmw_connextdds (#115)Revert “Refactor serialization support to use allocators and refs”Refactor serialization support to use allocators and refsAdd stubs for new rmw interfaces (#111)Add rmw_get_gid_for_client impl (#92)Switch ROS2 -> ROS 2 everywhere (#83)Contributors: Brian, Chris Lalancette, methylDragonrmw_connextdds_common[rmw_connextdds] New RMW discovery options (#108)Call get_type_hash_func (#113)Type hash distribution during discovery (rep2011) (#104)Implement matched event (#101)Add in implementation of inconsistent topic. (#103)Add rmw_get_gid_for_client impl (#92)Fix assert statement to allow the seconds field of a DDS_Duration_t to be zero (#88)Handle ‘best_available’ QoS policies in common (#85)Resolve build error with RTI Connext DDS 5.3.1 (#82)Contributors: Andrea Sorbini, Barry Xu, Brian, Chris Lalancette, Emerson Knapp, Grey, Jose Luis Rivero, Michael Carroll, Michael Jeronimormw_connextddsmicroDynamic Subscription (BONUS: Allocators): rmw_connextdds (#115)Add stubs for new rmw interfaces (#111)Add rmw_get_gid_for_client impl (#92)Switch ROS2 -> ROS 2 everywhere (#83)Contributors: Brian, Chris Lalancette, methylDragonrmw_cyclonedds_cppDynamic Subscription (BONUS: Allocators): rmw_cyclonedds (#451)Add stubs for new rmw interfaces (#447)[rmw_cyclonedds] Improve handling of dynamic discovery (#429)Call get_type_hash_func (#448)Type hash distribution in discovery (rep2011) (#437)Disable inconsistent topic events. (#444)Implement matched event (#435)Implement inconsistent topic. (#431)Make sure to add semicolons to the CHECK_TYPE_IDENTIFIER_MATCH. (#432)[rolling] Update maintainers - 2022-11-07 (#428)Export CycloneDDS dependency (#424)add NULL check before accessing object. (#423)Add rmw_get_gid_for_client impl (#402)Makes topic_name a const refAdds topic name to error msg when create_topic failsImprove error message when create_topic fails (#405)Change wrong use of %d to print uint32_t to PRIu32 (#253)Add cstring include. (#393)Handle ‘best_available’ QoS policies (#389)Contributors: Audrow Nash, Barry Xu, Brian, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Jose Luis Rivero, Shane Loretz, Tomoya Fujita, Tully Foote, Voldivh, eboasson, methylDragonrmw_dds_commonType hash in GraphCache, user_data encoding tools (#70)Mark benchmark _ as unused. (#71)Update rmw_dds_common to C++17. (#69)Change Gid.msg to be 16 bytes. (#68)Minor cleanups of test_qos. (#67)[rolling] Update maintainers - 2022-11-07 (#65)build shared lib only if BUILD_SHARED_LIBS is set (#62)Update maintainers (#61)Add functions for resolving ‘best available’ QoS policies (#60) Given a QoS profile and set of endpoints for the same topic, overwrite any policies set to BEST_AVAILABLE with a policy such that it matches all endpoints while maintaining a high level of service. Add testable functions for updating BEST_AVAILABLE policies, * qos_profile_get_best_available_for_subscription * qos_profile_get_best_available_for_publisher and add convenience functions that actual query the graph for RMW implementations to use, * qos_profile_get_best_available_for_topic_subscription * qos_profile_get_best_available_for_topic_publisherContributors: Audrow Nash, Chris Lalancette, Emerson Knapp, Jacob Perron, hannes09, methylDragonrmw_fastrtps_cppDynamic Subscription (BONUS: Allocators): rmw_fastrtps (#687)Runtime Interface Reflection: rmw_fastrtps (#655)[rmw_fastrtps] Improve handling of dynamic discovery (#653)Call get_type_hash_func (#680)Type hash distribution in discovery (rep2011) (#671)Implement inconsistent topic event (#654)Update all rmw_fastrtps packages to C++17. (#674)Rewrite how Topics are tracked in rmw_fastrtps_cpp. (#669)Allow loaned messages without data-sharing (#568)Fix incoherent dissociate_writer to dissociate_reader (#647) (#649)[rolling] Update maintainers - 2022-11-07 (#643)Add rmw_get_gid_for_client impl (#631)Use Fast-DDS Waitsets instead of listeners (#619)Remove rosidl_cmake dependency (#629)Revert “add line feed for RCUTILS_SAFE_FWRITE_TO_STDERR (#608)” (#612)add line feed for RCUTILS_SAFE_FWRITE_TO_STDERR (#608)Allow null arguments in the EventsExecutor parameters (#602)Add RMW_CHECKS to rmw_fastrtps_cpp EventsExecutor implementationHandle ‘best_available’ QoS policies (#598)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Jacob Perron, Jose Luis Rivero, Miguel Company, Oscarchoi, Ricardo González, Tomoya Fujita, methylDragonrmw_fastrtps_dynamic_cppDynamic Subscription (BONUS: Allocators): rmw_fastrtps (#687)Runtime Interface Reflection: rmw_fastrtps (#655)[rmw_fastrtps] Improve handling of dynamic discovery (#653)Call get_type_hash_func (#680)Type hash distribution in discovery (rep2011) (#671)Implement inconsistent topic event (#654)Update all rmw_fastrtps packages to C++17. (#674)Rewrite how Topics are tracked in rmw_fastrtps_cpp. (#669)Allow loaned messages without data-sharing (#568)Fix incoherent dissociate_writer to dissociate_reader (#647) (#649)[rolling] Update maintainers - 2022-11-07 (#643)Add rmw_get_gid_for_client impl (#631)Use Fast-DDS Waitsets instead of listeners (#619)Revert “add line feed for RCUTILS_SAFE_FWRITE_TO_STDERR (#608)” (#612)add line feed for RCUTILS_SAFE_FWRITE_TO_STDERR (#608)Allow null arguments in the EventsExecutor parameters (#602)Add EventExecutor to rmw_fastrtps_dynamic_cppFix cpplint error (#601)Handle ‘best_available’ QoS policies (#598)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Jacob Perron, Jose Luis Rivero, Miguel Company, Oscarchoi, Ricardo González, Tomoya Fujita, methylDragonrmw_fastrtps_shared_cppFix matched event issues (#683)Dynamic Subscription (BONUS: Allocators): rmw_fastrtps (#687)Check for triggered guard conditions before waiting (#685)Runtime Interface Reflection: rmw_fastrtps (#655)[rmw_fastrtps] Improve handling of dynamic discovery (#653)Type hash distribution in discovery (rep2011) (#671)Implement matched event (#645)Implement inconsistent topic event (#654)Update all rmw_fastrtps packages to C++17. (#674)Rewrite how Topics are tracked in rmw_fastrtps_cpp. (#669)Delay lock on message callback setters (#657)Make sure to add semicolons to the CHECK_TYPE_IDENTIFIER_MATCH. (#658)Allow loaned messages without data-sharing (#568)Fix incoherent dissociate_writer to dissociate_reader (#647) (#649)[rolling] Update maintainers - 2022-11-07 (#643)Remove duplicated code (#637)Call callbacks only if unread count > 0 (#634)Add rmw_get_gid_for_client impl (#631)Use Fast-DDS Waitsets instead of listeners (#619)Take all available samples on service/client on_data_available. (#616)Revert “add line feed for RCUTILS_SAFE_FWRITE_TO_STDERR (#608)” (#612)add line feed for RCUTILS_SAFE_FWRITE_TO_STDERR (#608)Contributors: Audrow Nash, Barry Xu, Brian, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Michael Carroll, Miguel Company, Oscarchoi, Ricardo González, Tomoya Fujita, mauropasse, methylDragonrmw_implementationDynamic Subscription (BONUS: Allocators): rmw_implementation (#219)Runtime Interface Reflection: rmw_implementation (#215)Mark the benchmark _ variables as unused. (#218)Update rmw_implementation to C++17. (#214)[rolling] Update maintainers - 2022-11-07 (#212)Build-time RMW selection does not need ament_index_cpp (#210)Add rmw_get_gid_for_client & tests (#206)Contributors: Audrow Nash, Brian, Chris Lalancette, G.A. vd. Hoorn, methylDragonrmw_implementation_cmake[rolling] Update maintainers - 2022-11-07 (#337)Contributors: Audrow Nashrobot_state_publisherUpdate robot_state_publisher to C++17. (#204)[rolling] Update maintainers - 2022-11-07 (#203)Mirror rolling to ros2Contributors: Audrow Nash, Chris Lalancetteros2actionMake all of the dependencies in pure Python packages exec_depend. (#823)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancetteros2bagCleanup the help text for ros2 bag record. (#1329) (#1333)Enable document generation using rosdoc2 for ament_python pkgs (#1260)CLI: Get storage-specific values from plugin (#1209)Fix up some of the wording in the record help text. (#1228)Add topic_name option to info verb (#1217)rosbag2_storage: set MCAP as default plugin (#1160)rosbag2_py: parametrize tests across storage plugins (#1203)Added option to change node name for the recorder from the Python API (#1180)rosbag2_cpp: test more than one storage plugin (#1196)rosbag2_storage: expose default storage ID as method (#1146)Fix for ros2 bag play exit with non-zero code on SIGINT (#1126)ros2bag: move storage preset validation to sqlite3 plugin (#1135)Add option to prevent message loss while converting (#1058)Added support for excluding topics via regular expressions (#1046)Readers/info can accept a single bag storage file, and detect its storage id automatically (#1072)Add short -v option to ros2 bag list for verbose (#1065)Use a single variable for evaluating the filter regex (#1053)Add additional mode of publishing sim time updates triggered by replayed messages (#1050)Renamed –topics-regex to –regex and -e in Player class to be consistent with Recorder (#1045)Use first available writer in recording if defaultsqlite3not available. (#1044)Add the ability to record any key/value pair in ‘custom’ field in metadata.yaml (#1038)Added support for filtering topics via regular expressions on Playback (#1034)Fix incorrect boundary check forplayback_durationandplay_until_timestamp(#1032)Adds play until timestamp functionality (#1005)Add CLI verb for burst mode of playback (#980)Add play-for specified number of seconds functionality (#960)Make unpublished topics unrecorded by default (#968)Contributors: Agustin Alba Chicar, Chris Lalancette, DensoADAS, Emerson Knapp, EsipovPA, Esteve Fernandez, Geoffrey Biggs, Hunter L.Allen, Keisuke Shima, Michael Orlov, Sean Kelly, Tony Peng, Yadu, james-rms, kylemarcey, mergify[bot], ricardo-manriquezros2cliSet automatically_declare_parameters_from_overrides in DirectNode. (#813)Enable document generation using rosdoc2 (#811)Fix linters (#808)add timeout option for ros2param to find node. (#802)Save method list via connection check to XMLRPC server. (#796)ZSH argcomplete: call compinit only if needed (#750)Fix network aware node issue (#785)[rolling] Update maintainers - 2022-11-07 (#776)XMLRPC server accepts request from all local IP addresses. (#729)Contributors: Audrow Nash, Chris Lalancette, Cristóbal Arroyo, Ivan Santiago Paunovic, Tomoya Fujita, Yadu, mjboguszros2cli_common_extensions[rolling] Update maintainers - 2022-11-07 (#7)Update maintainers (#6)Contributors: Audrow Nash, methylDragonros2cli_test_interfaces[rolling] Update maintainers - 2022-11-07 (#776)Remove action_msgs dependency (#743)Contributors: Audrow Nash, Jacob Perronros2componentEnable document generation using rosdoc2 (#811)[rolling] Update maintainers - 2022-11-07 (#776)Fix the component load help to mention load, not unload. (#756)Remove unused arguments from ros2 component types. (#711)Contributors: Audrow Nash, Chris Lalancette, Yaduros2doctorShutdown ros2doctor hello when ctrl-c is received (#829)Make all of the dependencies in pure Python packages exec_depend. (#823)Enable document generation using rosdoc2 (#811) * Fix warnings for ros2component, ros2doctor, ros2interface, and ros2node[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancette, Michael Carroll, Yaduros2interfaceMake all of the dependencies in pure Python packages exec_depend. (#823)Enable document generation using rosdoc2 (#811)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancette, Yaduros2launch[rolling] Update maintainers - 2022-11-07 (#331)Contributors: Audrow Nashros2lifecycleMake all of the dependencies in pure Python packages exec_depend. (#823)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancetteros2lifecycle_test_fixturesUpdate the ros2cli test fixture to C++17. (#789)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancetteros2multicastMake all of the dependencies in pure Python packages exec_depend. (#823)[rolling] Update maintainers - 2022-11-07 (#776)Add –group and –port options to ros2 multicast (#770)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzros2nodeMake all of the dependencies in pure Python packages exec_depend. (#823)Enable document generation using rosdoc2 (#811) * Fix warnings for ros2component, ros2doctor, ros2interface, and ros2nodeFix linters (#808)add timeout option for ros2param to find node. (#802)[rolling] Update maintainers - 2022-11-07 (#776)Updated wording in list.py (#775)Contributors: Audrow Nash, Chris Lalancette, Cristóbal Arroyo, Michael Wrock, Tomoya Fujita, Yaduros2paramremove deprecated options (#824)Make all of the dependencies in pure Python packages exec_depend. (#823)add timeout option for ros2param to find node. (#802)Fix printing of integer and double arrays. (#804)[rolling] Update maintainers - 2022-11-07 (#776)refactor: make ros2param use rclpy.parameter_client (#716)Contributors: Audrow Nash, Brian, Chris Lalancette, Tomoya Fujitaros2pkgFix typo in ros2pkg warning message. (#828)Make all of the dependencies in pure Python packages exec_depend. (#823)resolve#790(#801)Add alias library targets for CMake (#718)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancette, Kenji Brameld, RFRIEDM-Trimble, Tomoya Fujitaros2runMake all of the dependencies in pure Python packages exec_depend. (#823)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancetteros2serviceMake all of the dependencies in pure Python packages exec_depend. (#823)[rolling] Update maintainers - 2022-11-07 (#776)Contributors: Audrow Nash, Chris Lalancetteros2test[rolling] Update maintainers - 2022-11-07 (#12)update maintainerContributors: Audrow Nash, Dharini Dutia, quarkytaleros2topicremove deprecated options (#824)Make all of the dependencies in pure Python packages exec_depend. (#823)Expect type hash cli output in test (#822)Fix the type annotation in pub.py. (#814)Switch to using new event_handler instead of qos_event. (#787)avoid flaky test that subscriber might not receive the message (#810)Adds a--max-wait-timeoption toros2topicpub(#800)Fix some flake8 warnings related to style. (#805)Adds a timeout feature to rostopic echo (#792)Refactor common types (#791)Allow configuring liveliness in ros2 topic echo and pub (#788)Extend timeout to shutdown the command line process. (#783)[rolling] Update maintainers - 2022-11-07 (#776)a couple of typo fixes. (#774)Add support use_sim_time for ros2 topic hz/bw/pub. (#754)Use set_message_fields from rosidl_runtime_py (#761)Expand auto to the current time when passed to a Header field (#749)Add verbose option to echo that also prints the associated message info (#707)update docs for bandwidth functions. (#709)Split the bandwidth functions into a get and print. (#708)Contributors: Arjo Chakravarty, Audrow Nash, Chen Lihui, Chris Lalancette, Emerson Knapp, Esteve Fernandez, Ivan Santiago Paunovic, Lei Liu, Tomoya Fujitaros2traceMove ros2trace tests to new test_ros2trace package (#63)Error out if trace already exists unless ‘append’ option is used (#58)Improve ‘ros2 trace’ command error handling & add end-to-end tests (#54)Contributors: Christophe Bedardros_testing[rolling] Update maintainers - 2022-11-07 (#12)update maintainerContributors: Audrow Nash, Dharini Dutia, quarkytalerosbag2Add Michael Orlov as maintainer in rosbag2 packages (#1215)Move sqlite3 storage implementation to rosbag2_storage_sqlite3 package (#1113)Contributors: Emerson Knapp, Michael Orlovrosbag2_compressionAdd in a missing cstdint include. (#1321) (#1322)Fix warning from ClassLoader in sequential compression reader and writer (#1299) (#1316)Add message definition read API (#1292)rosbag2_storage: add type description hash to topic metadata (#1272)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)set_read_order: return success (#1177)Addupdate_metadata(BagMetadata)API for storage plugin interface (#1149)Reverse read order API and sqlite storage implementation (#1083)Add option to prevent message loss while converting (#1058)set default metadata of compressed message (in case compressor does not set it) (#1060)Speed optimization: Preparing copyless publish/subscribing by using const message for writing (#1010)Add the ability to record any key/value pair in ‘custom’ field in metadata.yaml (#1038)Contributors: Chris Lalancette, Daisuke Nishimatsu, DensoADAS, Emerson Knapp, Hunter L. Allen, Joshua Hampp, Michael Orlov, Tony Peng, james-rms, mergify[bot]rosbag2_compression_zstdUpdate rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Speed optimization: Preparing copyless publish/subscribing by using const message for writing (#1010)Contributors: Chris Lalancette, Daisuke Nishimatsu, DensoADAS, Joshua Hampp, Michael Orlovrosbag2_cppAdd recorder stop() API (#1300) (#1334)Add type_hash in MessageDefinition struct (#1296)Add message definition read API (#1292)rosbag2_storage: add type description hash to topic metadata (#1272)Fix for flakyTimeControllerClockTest::unpaused_sleep_returns_truetest (#1290)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)Fix rwm->rmw spelling (#1249)Expose more Writer methods in python interface (#1220)rosbag2_storage: set MCAP as default plugin (#1160)Parametrize all rosbag2_tests for both supported storage plugins (#1221)rosbag2_cpp: test more than one storage plugin (#1196)Replace language for “db3”/”db”/”database” (#1194)set_read_order: return success (#1177)Remove explicit sqlite3 from code (#1166)Addupdate_metadata(BagMetadata)API for storage plugin interface (#1149)Reader and writer can use default storage by not specifying (#1167)rosbag2_storage: expose default storage ID as method (#1146)Don’t reopen file for every seek if we don’t have to. Search directionally for the correct file (#1117)Add SplitBagfile recording service. (#1115)Reverse read order API and sqlite storage implementation (#1083)Replacestd::filesystem::path(..)withrcpputils::fs::path(..)(#1104)Fix issue where sequentialwriter only sets metadata duration to the duration of the final file (#1098)Delete obsolete compression_options.cpp from rosbag2_cpp (#1078)Readers/info can accept a single bag storage file, and detect its storage id automatically (#1072)Remove deprecated rosbag2_cpp/storage_options.hpp, for post-Humble releases (#1064)Speed optimization: Preparing copyless publish/subscribing by using const message for writing (#1010)Add the ability to record any key/value pair in ‘custom’ field in metadata.yaml (#1038)Notification of significant events during bag recording and playback (#908)Bugfix for “Playing the bags recorded with split by duration/size is playing only the last recorded .db3.” (#1022)Improve test_time_controller test (#1012)Contributors: Chris Lalancette, Daisuke Nishimatsu, DensoADAS, Emerson Knapp, Geoffrey Biggs, Hunter L. Allen, Jorge Perez, Joshua Hampp, Kaju-Bubanja, Michael Orlov, Tony Peng, james-rms, mergify[bot], rshanorrosbag2_examples_cpprosbag2_storage: add type description hash to topic metadata (#1272)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Add API samples on main branch - Rolling C++ API examples (#1068)Contributors: Chris Lalancette, Daisuke Nishimatsu, Emerson Knapp, Michael Orlov, james-rmsrosbag2_examples_pyFix a warning from python setuptools. (#1312) (#1314)Add API samples for Python [rebased] (#1253) * Add API samples for Python * Package Renaming and Move * linting + copyright * more linting ——— Co-authored-by: Geoffrey Biggs Contributors: David V. Lu!!, mergify[bot]rosbag2_interfacesUpdate rosbag2 to C++17. (#1238)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Add SplitBagfile recording service. (#1115)Adds stop operation for rosbag2::Player (#1007)Notification of significant events during bag recording and playback (#908)Adds play until timestamp functionality (#1005)Add CLI verb for burst mode of playback (#980)Add play-for specified number of seconds functionality (#960)Contributors: Agustin Alba Chicar, Chris Lalancette, Geoffrey Biggs, Michael Orlov, Misha Shalem, rshanorrosbag2_performance_benchmarkingAdd tests for rosbag2_performance_benchmarking pkg (#1268)Fix expectations for rosbag2 return code in rosbag2_performance_benchmarking (#1267)Update rosbag2 to C++17. (#1238)Use thread pool to run benchmark publishers in rosbag2_performance_benchmarking (#1250)Use target_link_libraries instead of ament_target_dependencies (#1202)Skip ament_package() call when not building rosbag2_performance_benchmarking (#1242)Add option to specify a message type (#1153)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Replace language for “db3”/”db”/”database” (#1194)Remove explicit sqlite3 from code (#1166)Contributors: Chris Lalancette, Daisuke Nishimatsu, Emerson Knapp, Michael Orlov, Shane Loretz, carlossvgrosbag2_performance_benchmarking_msgsAdd tests for rosbag2_performance_benchmarking pkg (#1268)Skip ament_package() call when not building rosbag2_performance_benchmarking (#1242)[rolling] Bump to 0.19.0 (#1232)Add option to specify a message type (#1153)Contributors: Audrow Nash, Michael Orlov, Shane Loretz, carlossvgrosbag2_pyAdd binding to close the writer (#1339) (#1340)Add type_hash in MessageDefinition struct (#1296)Store message definitions in SQLite3 storage plugin (#1293)Add message definition read API (#1292)rosbag2_storage: add type description hash to topic metadata (#1272)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)Expose more Writer methods in python interface (#1220)rosbag2_storage: set MCAP as default plugin (#1160)Add Michael Orlov as maintainer in rosbag2 packages (#1215)rosbag2_py: parametrize tests across storage plugins (#1203)Added option to change node name for the recorder from the Python API (#1180)Replace language for “db3”/”db”/”database” (#1194)Remove explicit sqlite3 from code (#1166)Move python get_default_storage_id to storage module instead of writer (#1165)rosbag2_storage: expose default storage ID as method (#1146)rosbag2_py: set defaults for config when bag rewriting (#1121)Reverse read order API and sqlite storage implementation (#1083)expose py Reader metadata, improverosbag2_py.BagMetadatausability (#1082)Added support for excluding topics via regular expressions (#1046)Use a single variable for evaluating the filter regex (#1053)Add additional mode of publishing sim time updates triggered by replayed messages (#1050)Renamed –topics-regex to –regex and -e in Player class to be consistent with Recorder (#1045)Add the ability to record any key/value pair in ‘custom’ field in metadata.yaml (#1038)Added support for filtering topics via regular expressions on Playback (#1034)Adds play until timestamp functionality (#1005)Add CLI verb for burst mode of playback (#980)Add play-for specified number of seconds functionality (#960)Make unpublished topics unrecorded by default (#968)Fix test rosbag2_py test compatibility with Python < 3.8 (#987)Contributors: Agustin Alba Chicar, Chris Lalancette, Daisuke Nishimatsu, Emerson Knapp, Esteve Fernandez, Geoffrey Biggs, Hunter L. Allen, Michael Orlov, Scott K Logan, Sean Kelly, Tony Peng, james-rms, kylemarcey, mergify[bot], ricardo-manriquezrosbag2_storageAdd type_hash in MessageDefinition struct (#1296)Add message definition read API (#1292)rosbag2_storage: add type description hash to topic metadata (#1272)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)rosbag2_storage: set MCAP as default plugin (#1160)Add Michael Orlov as maintainer in rosbag2 packages (#1215)set_read_order: return success (#1177)Remove explicit sqlite3 from code (#1166)Addupdate_metadata(BagMetadata)API for storage plugin interface (#1149)rosbag2_storage: expose default storage ID as method (#1146)Don’t reopen file for every seek if we don’t have to. Search directionally for the correct file (#1117)Reverse read order API and sqlite storage implementation (#1083)Remove YAML_CPP_DLL define (#964)Added support for excluding topics via regular expressions (#1046)Readers/info can accept a single bag storage file, and detect its storage id automatically (#1072)Use a single variable for evaluating the filter regex (#1053)Speed optimization: Preparing copyless publish/subscribing by using const message for writing (#1010)Renamed –topics-regex to –regex and -e in Player class to be consistent with Recorder (#1045)Add the ability to record any key/value pair in ‘custom’ field in metadata.yaml (#1038)Added support for filtering topics via regular expressions on Playback (#1034)Contributors: Akash, Chris Lalancette, Daisuke Nishimatsu, DensoADAS, Emerson Knapp, Esteve Fernandez, Hunter L. Allen, Joshua Hampp, Michael Orlov, Tony Peng, james-rmsrosbag2_storage_default_pluginsrosbag2_storage: set MCAP as default plugin (#1160)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Move sqlite3 storage implementation to rosbag2_storage_sqlite3 package (#1113)Reverse read order API and sqlite storage implementation (#1083)Add support for old db3 schema used on distros prior to Foxy (#1090)Added support for excluding topics via regular expressions (#1046)Contributors: Emerson Knapp, Esteve Fernandez, Michael Orlov, james-rmsrosbag2_storage_mcapAdd type_hash in MessageDefinition struct (#1296)Add message definition read API (#1292)rosbag2_storage: add type description hash to topic metadata (#1272)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)CLI: Get storage-specific values from plugin (#1209)Add Michael Orlov as maintainer in rosbag2 packages (#1215)rosbag2_cpp: test more than one storage plugin (#1196)set_read_order: return success (#1177)rosbag2_storage_mcap: merge into rosbag2 repo (#1163)mcap_storage: ‘none’ is a valid storage preset profile (#86)mcap_storage: handle update_metadata call (#83)Update clang-format rules to fit ROS 2 style guide (#80)Revert “read_order: throw exception from set_read_order for unsupported orders”read_order: throw exception from set_read_order for unsupported ordersFix compile flags to work on rosbag_storage:0.17.x (#78)Fix Windows build (#73)set defaults for SQLite plugin parity (#68)rosbag2_storage_mcap: add storage preset profiles (#57)rename test_fixture_interfaces package to testdata (#64)Switch to using the vendored zstd library. (#59)Add set_read_order reader API (#54)Some minor improvements in rosbag2_storage_mcap after review (#58)Revert “rosbag2_storage_mcap: add storage preset profiles”rosbag2_storage_mcap: add storage preset profilesStore IDL message definitions in Schema records when no MSG definition is available (#43)Support timestamp-ordered playback (#50)Support regex topic filteringAdd all lz4 sources to fix undefined symbols at runtime (#46)Upgrade mcap to fix LZ4 error and segfault (#42)Fix build for Foxy (#34)fix: minor issues (#31) * remove unnecessary block * use target_link_libraries instead of ament_target_dependencies * remove ros environment * add prefix to compile definitionUpdate email address for Foxglove maintainers (#32)Added mcap_vendor package. Updated CMakeLists.txt to fetch dependencies with FetchContent rather than Conan.CMake build script will now execute pip install conan automatically.[1.0.0] Use Summary section for get_metadata() and seek(), implement remaining methods (#17)feat: add play impl (#16)chore: refine package.xml (#15)Don’t throw when READ_WRITE mode is used; add .mcap file extension to recorded files (#14)Add dynamic message definition lookup (#13)Switch C++ formatter to clang-format (#12)Merge pull request#7from ros-tooling/jhurliman/reader-writeruninitialized structlintlintlintReader and writer implementationMerge pull request#6from wep21/add-metadata-implfeat: add metadata implMerge pull request#5from wep21/mcap-storage-implchore: update cmake minimum versionchore: install mcap headerchore: include mcap headerfix: move fetch content into rosbag2 storage mcapMerge pull request#3from ros-tooling/emersonknapp/mcap_plugin_skeletonAdd rosbag2_storage_mcap skeletonContributors: Andrew Symington, Chris Lalancette, Daisuke Nishimatsu, Emerson Knapp, Jacob Bandes-Storch, James Smith, John Hurliman, Michael Orlov, james-rms, wep21rosbag2_storage_sqlite3Add type_hash in MessageDefinition struct (#1296)Store message definitions in SQLite3 storage plugin (#1293)Add message definition read API (#1292)rosbag2_storage: add type description hash to topic metadata (#1272)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)CLI: Get storage-specific values from plugin (#1209)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Remove sqlite3-specific info from main README, make it more storage agnostic and point to plugin-specific README (#1193)set_read_order: return success (#1177)Addupdate_metadata(BagMetadata)API for storage plugin interface (#1149)Store db schema version and ROS_DISTRO name in db3 files (#1156)ros2bag: move storage preset validation to sqlite3 plugin (#1135)Move sqlite3 storage implementation to rosbag2_storage_sqlite3 package (#1113)Use a single variable for evaluating the filter regex (#1053)Renamed –topics-regex to –regex and -e in Player class to be consistent with Recorder (#1045)Added support for filtering topics via regular expressions on Playback (#1034)Contributors: Chris Lalancette, Daisuke Nishimatsu, Emerson Knapp, Esteve Fernandez, Michael Orlov, james-rmsrosbag2_test_commonAddress flakiness in rosbag2_play_end_to_end tests (#1297) (#1330)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)Add Michael Orlov as maintainer in rosbag2 packages (#1215)rosbag2_py: parametrize tests across storage plugins (#1203)Fix for ros2 bag play exit with non-zero code on SIGINT (#1126)Split up the include of rclcpp.hpp (#1027)Contributors: Chris Lalancette, Daisuke Nishimatsu, Michael Orlov, james-rms, mergify[bot]rosbag2_test_msgdefsrosbag2_cpp: move local message definition source out of MCAP plugin (#1265) The intention of this PR is to move the message-definition-finding capability outside of rosbag2_storage_mcap, and allow any rosbag2 storage plugin to store message definitions.Contributors: james-rmsrosbag2_testsAddress flakiness in rosbag2_play_end_to_end tests (#1297) (#1330)Add type_hash in MessageDefinition struct (#1296)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)rosbag2_storage: set MCAP as default plugin (#1160)Add Michael Orlov as maintainer in rosbag2 packages (#1215)Parametrize all rosbag2_tests for both supported storage plugins (#1221)Make rosbag2_tests agnostic to storage implementation (#1192)Get rid from attempt to open DB file inwait_for_db()test fixture (#1141)Fix for ros2 bag play exit with non-zero code on SIGINT (#1126)Move sqlite3 storage implementation to rosbag2_storage_sqlite3 package (#1113)Readers/info can accept a single bag storage file, and detect its storage id automatically (#1072)Add the ability to record any key/value pair in ‘custom’ field in metadata.yaml (#1038)Contributors: Chris Lalancette, Daisuke Nishimatsu, Emerson Knapp, Hunter L. Allen, Michael Orlov, Tony Peng, james-rms, mergify[bot]rosbag2_transportChange subscriptions from GenericSubscripton to SubscriptionBase (#1338)Add recorder stop() API (#1300) (#1334)Read message definitions from input files in bag_rewrite (#1295)Add message definition read API (#1292)Move rosbag2_transport::Recorder implementation to pimpl (#1291)rosbag2_storage: add type description hash to topic metadata (#1272)rosbag2_cpp: move local message definition source out of MCAP plugin (#1265)Use RMW methods to initialize endpoint info instead of brace initializer to guard against upcoming struct change (#1257)Update rosbag2 to C++17. (#1238)Use target_link_libraries instead of ament_target_dependencies (#1202)Print “Hidden topics are not recorded” only once. (#1225)rosbag2_storage: set MCAP as default plugin (#1160)Add Michael Orlov as maintainer in rosbag2 packages (#1215)rosbag2_transport: parametrize test_rewrite (#1206)rosbag2_cpp: test more than one storage plugin (#1196)Replace language for “db3”/”db”/”database” (#1194)set_read_order: return success (#1177)Remove explicit sqlite3 from code (#1166)Add pause and resume service calls for rosbag2 recorder (#1131)Redesign record_services tests to make them more deterministic (#1122)Add SplitBagfile recording service. (#1115)Reverse read order API and sqlite storage implementation (#1083)make recorder node composable by inheritance (#1093)Marktest_play_servicesas xfail for FastRTPS and CycloneDDS (#1091)fixed typo (#1057)Fix hangout in rosbag2 player and recorder when pressingCTRL+C(#1081)Added support for excluding topics via regular expressions (#1046)Use a single variable for evaluating the filter regex (#1053)Add additional mode of publishing sim time updates triggered by replayed messages (#1050)Speed optimization: Preparing copyless publish/subscribing by using const message for writing (#1010)Renamed –topics-regex to –regex and -e in Player class to be consistent with Recorder (#1045)Refactor play until and duration tests (#1024)Added support for filtering topics via regular expressions on Playback (#1034)Adds stop operation for rosbag2::Player (#1007)Fix incorrect boundary check forplayback_durationandplay_until_timestamp(#1032)Split up the include of rclcpp.hpp (#1027)Notification of significant events during bag recording and playback (#908)Adds play until timestamp functionality (#1005)Add CLI verb for burst mode of playback (#980)Add on play message callbacks to therosbag2::Playerclass (#1004)Add play-for specified number of seconds functionality (#960)Reduce message spam when topics to be recorded do not exist (#1018)Address flakiness in record_all_with_sim_time test (#1014)Add debug instrumentation fortest_play_services(#1013)Fix for rosbag2::Player freeze when pressing ctrl+c in pause mode (#1002)Add the /bigobj flag to Windows Debug builds. (#1009)Make unpublished topics unrecorded by default (#968)Make peek_next_message_from_queue return a SharedPtr. (#993)Change the topic names in test_record.cpp (#988)Contributors: Agustin Alba Chicar, Bernardo Taveira, Brian, Chris Lalancette, Cristóbal Arroyo, Daisuke Nishimatsu, DensoADAS, Emerson Knapp, Esteve Fernandez, Geoffrey Biggs, Jorge Perez, Joshua Hampp, Michael Orlov, Misha Shalem, Sean Kelly, Tony Peng, james-rms, kylemarcey, mergify[bot], rshanorrosgraph_msgsUpdate common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)Contributors: Audrow Nash, Chris Lalancetterosidl_adapterrosidl_adapter/cmake/rosidl_adapt_interfaces.cmake: Make ament free (#709)[service introspection] generate service_event messages (#700)Adding tests for unicode support in message comments. (#720)[rolling] Update maintainers - 2022-11-07 (#717)Add action2idl script (#654)Contributors: Audrow Nash, Brian, Guilherme Henrique Galelli Christmann, John Daktylidis, Yasushi SHOJIrosidl_cliFix warnings (#726)[rolling] Update maintainers - 2022-11-07 (#717)Contributors: Audrow Nash, Yadurosidl_cmakeType Description Codegen and Typesupport (rep2011) (#727)Type hash in interface codegen (rep2011) (#722)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Skip rosidl_generate_interfaces dependency export on SKIP_INSTALL. (#708)Move rosidl_cmake Python module to a new package rosidl_pycommon (#696) Deprecate the Python module in rosidl_cmake and move the implementation to the new package rosidl_pycommon.Fix comment in camel case conversion function (#683)Protect rosidl_target_interfaces from using NOTFOUND in include_directories (#679)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Jacob Perron, Jose Luis Rivero, Shane Loretzrosidl_core_generators[rolling] Update maintainers - 2022-11-07 (#2)Add generators and runtime configuration packages (#1) Moved (and renamed) from rosidl_defaults. Related PR:https://github.com/ros2/rosidl_defaults/pull/22Contributors: Audrow Nash, Jacob Perronrosidl_core_runtime[rolling] Update maintainers - 2022-11-07 (#2)Add generators and runtime configuration packages (#1) Moved (and renamed) from rosidl_defaults. Related PR:https://github.com/ros2/rosidl_defaults/pull/22Contributors: Audrow Nash, Jacob Perronrosidl_default_generatorsadd service_msgs depend (#24)[rolling] Update maintainers - 2022-11-07 (#25)Move dependencies to rosidl_core and depend on action_msgs (#22) Move implementation to new packages rosidl_core_generators and rosidl_runtime_generators The new packages are located in a separate repository:https://github.com/ros2/rosidl_core.gitrosidl_defaults now depends on the new packages, plus message definitions required for Actions (namely action_msgs). This allows users to avoid having to explictly depend on action_msgs.Contributors: Audrow Nash, Brian, Jacob Perronrosidl_default_runtimeadd service_msgs depend (#24)[rolling] Update maintainers - 2022-11-07 (#25)Move dependencies to rosidl_core and depend on action_msgs (#22) Move implementation to new packages rosidl_core_generators and rosidl_runtime_generators The new packages are located in a separate repository:https://github.com/ros2/rosidl_core.gitrosidl_defaults now depends on the new packages, plus message definitions required for Actions (namely action_msgs). This allows users to avoid having to explictly depend on action_msgs.Contributors: Audrow Nash, Brian, Jacob Perronrosidl_dynamic_typesupportFix up the exports for rosidl_dynamic_typesupport. (#5)Refactor dynamic message type support impl to use allocators (#2)Runtime Interface Reflection: rosidl_dynamic_typesupport (#1)Contributors: Chris Lalancette, William Woodall, methylDragonrosidl_dynamic_typesupport_fastrtpsRemove more unnecessary semicolons (#4)Dynamic Subscription (BONUS: Allocators): rosidl_dynamic_typesupport_fastrtps (#3)Remove unnecessary semicolons. (#2)Runtime Interface Reflection: rosidl_dynamic_typesupport_fastrtps (#1)Contributors: Chris Lalancette, methylDragonrosidl_generator_cType Description Codegen and Typesupport (rep2011) (#727)Expose type hash on typesupports (rep2011) (#729)Type hash in interface codegen (rep2011) (#722)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Move rosidl_generator_c/cpp tests to a separate package (#701)Move rosidl_cmake Python module to a new package rosidl_pycommon (#696) Deprecate the Python module in rosidl_cmake and move the implementation to the new package rosidl_pycommon.Add namespaced ALIAS target to easily consume generated libraries via add_subdirectory (#605)Contributors: Audrow Nash, Brian, Emerson Knapp, Jacob Perron, Silvio Traversarorosidl_generator_cppType Description Codegen and Typesupport (rep2011) (#727)Expose type hash on typesupports (rep2011) (#729)Type hash in interface codegen (rep2011) (#722)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Move rosidl_generator_c/cpp tests to a separate package (#701)Move rosidl_cmake Python module to a new package rosidl_pycommon (#696) Deprecate the Python module in rosidl_cmake and move the implementation to the new package rosidl_pycommon.Add namespaced ALIAS target to easily consume generated libraries via add_subdirectory (#605)Contributors: Audrow Nash, Brian, Emerson Knapp, Jacob Perron, Silvio Traversarorosidl_generator_dds_idl[rolling] Update maintainers - 2022-11-07 (#60)Replace rosidl_cmake imports with rosidl_pycommon (#59)Contributors: Audrow Nash, Jacob Perronrosidl_generator_pyHides the assertions that checks the data types of the message fields. (#194)Service introspection (#178)[rolling] Update maintainers - 2022-11-07 (#189)Remove stray numpy import (#185)man_farmer:Fix NaN values bound numpy windows version (#182)Allow NaN values to pass floating point bounds check. (#167)Replace rosidl_cmake imports with rosidl_pycommon (#177)Change decode error mode to replace (#176)Merge pull request#173from ros2/quarkytale/fix_import_orderfix flakesorting after conversionRevert “Use modern cmake targets to avoid absolute paths to appear in binary archives (#160)” (#166)Use modern cmake targets to avoid absolute paths to appear in binary archives (#160)michel as authoradding maintainerContributors: Audrow Nash, Ben Wolsieffer, Brian, Cristóbal Arroyo, Dharini Dutia, Eloy Briceno, Ivan Santiago Paunovic, Jacob Perron, Tomoya Fujita, quarkytale, Øystein Sturerosidl_generator_testsType Description Codegen and Typesupport (rep2011) (#727)Type hash in interface codegen (rep2011) (#722)[service introspection] generate service_event messages (#700) * add service event message[rolling] Update maintainers - 2022-11-07 (#717)Move rosidl_generator_c/cpp tests to a separate package (#701)Contributors: Audrow Nash, Brian, Emerson Knapp, Jacob Perronrosidl_generator_type_descriptionType Description Codegen and Typesupport (rep2011) (#727)Expose type hash on typesupports (rep2011) (#729)Type hash in interface codegen (rep2011) (#722)Contributors: Emerson Knapprosidl_parser[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Always include whitespace in string literals (#688)Contributors: Audrow Nash, Brian, Shane Loretzrosidl_pycommonType Description Codegen and Typesupport (rep2011) (#727)Type hash in interface codegen (rep2011) (#722)[rolling] Update maintainers - 2022-11-07 (#717)Move rosidl_cmake Python module to a new package rosidl_pycommon (#696) Deprecate the Python module in rosidl_cmake and move the implementation to the new package rosidl_pycommon.Contributors: Audrow Nash, Emerson Knapp, Jacob Perronrosidl_runtime_cDynamic Subscription (BONUS: Allocators): rosidl (#737)Runtime Interface Reflection: rosidl (#728)Type Description Codegen and Typesupport (rep2011) (#727)Copied type_description_interfaces structs (rep2011) (#732)Expose type hash on typesupports (rep2011) (#729)Type hash in interface codegen (rep2011) (#722)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Contributors: Audrow Nash, Brian, Emerson Knapp, methylDragonrosidl_runtime_cppType Description Codegen and Typesupport (rep2011) (#727)Copied type_description_interfaces structs (rep2011) (#732)Fix a few more clang analysis problems. (#731)Return reference from BoundedVector::emplace_back (#730)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)fix conversion to ‘std::streamsize’ {aka ‘long int’} from ‘size_t’ {aka ‘long unsigned int’} may change the sign of the result (#715)Contributors: Alexander Hans, Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, ralwingrosidl_runtime_pyReplace the use __slots__ for the appropiate API (#23)fix(typing):get_interface_packagesreturns a dict (#22)[rolling] Update maintainers - 2022-11-07 (#21)Expand timestamps for std_msgs.msg.Header and builtin_interfaces.msg.Time if ‘auto’ and ‘now’ are passed as values (#19)Document a missing parameter in message_to_yaml. (#18)Mirror rolling to masterContributors: Audrow Nash, Chris Lalancette, Eloy Briceno, Esteve Fernandez, 兰陈昕rosidl_typesupport_cType Description Nested Support (#141)Fix rosidl_typesupport_c/cpp exec dependencies. (#140)Type hashes in typesupport (rep2011) (#135)Mark benchmark _ as UNUSED. (#134)Service introspection (#127)Update rosidl_typesupport to C++17. (#131)[rolling] Update maintainers - 2022-11-07 (#130)Replace rosidl_cmake imports with rosidl_pycommon (#126)[service introspection] Use stddef.h instead of cstddef (#125)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Jacob Perronrosidl_typesupport_cppType Description Nested Support (#141)Fix rosidl_typesupport_c/cpp exec dependencies. (#140)Type hashes in typesupport (rep2011) (#135)Mark benchmark _ as UNUSED. (#134)Service introspection (#127)Update rosidl_typesupport to C++17. (#131)[rolling] Update maintainers - 2022-11-07 (#130)Replace rosidl_cmake imports with rosidl_pycommon (#126)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Jacob Perronrosidl_typesupport_fastrtps_cType Description Nested Support (#101)Type hashes on typesupport (rep2011) (#98)Expose type hash to typesupport structs (rep2011) (#95)Mark benchmark _ as UNUSED. (#96)Service introspection (#92)Update rosidl_typesupport_fastrtps to C++17. (#94)[rolling] Update maintainers - 2022-11-07 (#93)Replace rosidl_cmake imports with rosidl_pycommon (#91)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Jacob Perronrosidl_typesupport_fastrtps_cppType Description Nested Support (#101)Type hashes on typesupport (rep2011) (#98)Depend on ament_cmake_ros to default SHARED to ON (#99)Expose type hash to typesupport structs (rep2011) (#95)Mark benchmark _ as UNUSED. (#96)Service introspection (#92)Update rosidl_typesupport_fastrtps to C++17. (#94)[rolling] Update maintainers - 2022-11-07 (#93)Replace rosidl_cmake imports with rosidl_pycommon (#91)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Jacob Perron, Tyler Weaverrosidl_typesupport_interface[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Contributors: Audrow Nash, Brianrosidl_typesupport_introspection_cType Description Codegen and Typesupport (rep2011) (#727)Expose type hash on typesupports (rep2011) (#729)Type hash in interface codegen (rep2011) (#722)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Move rosidl_cmake Python module to a new package rosidl_pycommon (#696) Deprecate the Python module in rosidl_cmake and move the implementation to the new package rosidl_pycommon.Fix build export dependencies in C introspection package (#695)Add namespaced ALIAS target to easily consume generated libraries via add_subdirectory (#605)Contributors: Audrow Nash, Brian, Emerson Knapp, Jacob Perron, Silvio Traversarorosidl_typesupport_introspection_cppType Description Codegen and Typesupport (rep2011) (#727)Expose type hash on typesupports (rep2011) (#729)Type hash in interface codegen (rep2011) (#722)Make sure to add the event message to typesupport introspection cpp. (#724)[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Move rosidl_cmake Python module to a new package rosidl_pycommon (#696) Deprecate the Python module in rosidl_cmake and move the implementation to the new package rosidl_pycommon.Add namespaced ALIAS target to easily consume generated libraries via add_subdirectory (#605)Contributors: Audrow Nash, Brian, Chris Lalancette, Emerson Knapp, Jacob Perron, Silvio Traversarorosidl_typesupport_introspection_testsFix a few more clang analysis problems. (#731) In particular, make sure to mark the fact that we are C++17 (as the emplace_back signature changed), and also add in a few more (void)_ for benchmark tests.[service introspection] generate service_event messages (#700)[rolling] Update maintainers - 2022-11-07 (#717)Contributors: Audrow Nash, Brian, Chris Lalancetterosidl_typesupport_teststypesupport_tests needs to be updated to C++17 (#137)Fix Typesupport Introspection tests (#133)Make rosidl_typesupport_tests depend on rosidl_generator_cpp. (#132)Service introspection (#127)Contributors: Brian, Chris Lalancette, Cristóbal Arroyo, Lucas Wendlandrpyutils[rolling] Update maintainers - 2022-11-07 (#10)Mirror rolling to masterupdating maintainerContributors: Audrow Nash, Dharini Dutiarqtfix build ofrqtwithsetuptools>=v61.0.0(#271)[rolling] Update maintainers - 2022-11-07 (#283)Fix up the package description. (#250)Contributors: Audrow Nash, Chris Lalancette, Daniel Reuter, Dharini Dutia, quarkytalerqt_action[rolling] Update maintainers - 2022-11-07 (#14)Small cleanups to the rqt_action plugin (#13)Mirror rolling to ros2Contributors: Audrow Nash, Chris Lalancetterqt_bagUse default storage id (#140)Use rosbag2_py API instead of direct bag parsing[rolling] Update maintainers - 2022-11-07 (#132)For get_entry_after, bump by 1 nanosecond otherwise always get the same message equal to the timestampUse rosbag2_py.reader for all message queries, remove sqlite3 direct usageCleanup for reviewImproved loggingUse a rosbag2_py.Reader to get bag metadataDisable reading from bag while recording - use direct caching to index for timelineIncrease publishing checkbox size (#122)Fix toggle thumbnails button (#117)ensure data types match what PyQt expects (#118)Visualize topics being published and highlight topic being selected (#116)Be able to scroll up and down, not only zoom-in and out the timeline (#114)[Fixes] Fix crash when no qos metadata, make scroll bar appear if needed, add gitignore (#113)Fix the types being passed into QFont and QColor. (#109)Fix tuples for bisect calls (#67) (#76)fix long topic names (#114)fix zoom behavior (#76)Contributors: Audrow Nash, Chris Lalancette, Emerson Knapp, Ivan Santiago Paunovic, Kenji Brameld, Yadunundrqt_bag_pluginsChanges the use of __slots__ for the field and field type getter (#138)[rolling] Update maintainers - 2022-11-07 (#132)Contributors: Audrow Nash, Eloy Bricenorqt_console[rolling] Update maintainers - 2022-11-07 (#39)added new maintainerContributors: Arne Hitzmann, Audrow Nashrqt_graphRefresh rosgraph when params checkbox is clicked (#87)[rolling] Update maintainers - 2022-11-07 (#83)Minor cleanup (#80)Mirror rolling to galactic-develgraph load/save into DOT file corrections for py3 (#78)Remove repeated prefixes from buttonsContributors: Audrow Nash, Chris Lalancette, David V. Lu!!, Yadunund, mergify[bot]rqt_gui[rolling] Update maintainers - 2022-11-07 (#283)Display basic help information when no plugins are loaded (#268)Contributors: Audrow Nash, Dharini Dutia, Michael Jeronimo, quarkytalerqt_gui_cppUpdate rqt to C++17. (#285)[rolling] Update maintainers - 2022-11-07 (#283)Contributors: Audrow Nash, Chris Lalancette, Dharini Dutia, quarkytalerqt_gui_pyFix an exception raised when terminating with Ctrl+c (#292)[rolling] Update maintainers - 2022-11-07 (#283)Contributors: Audrow Nash, Chen Lihui, Dharini Dutia, quarkytalerqt_msg[rolling] Update maintainers - 2022-11-07 (#17)Contributors: Audrow Nashrqt_plotFix regression from #87 (#91)Changes the use of __slots__ for the field and field type getter (#87)[rolling] Update maintainers - 2022-11-07 (#83)Fix fixed-size Array visualization (#81)Contributors: Audrow Nash, Eloy Briceno, Jacob Perron, Michael Jeronimo, Yadunundrqt_publisherChanges the use of __slots__ for the field and field type getter[rolling] Update maintainers - 2022-11-07 (#36)Minor cleanups in rqt_publisher for ROS 2 (#35)Delete sync to foxy-devel workflowMerge pull request#33from NBadyal/improve-evaluation-of-typesUse regex matching to strip errors from inputChange slot_type verification strategyMirror rolling to foxy-develContributors: Audrow Nash, Chris Lalancette, Geoffrey Biggs, Michael Jeronimo, Nicholas Badyal, Voldivhrqt_py_commonChanges the use of __slots__ for the field and field type getter (#289)[rolling] Update maintainers - 2022-11-07 (#283)Contributors: Audrow Nash, Dharini Dutia, Eloy Briceno, quarkytalerqt_py_console[rolling] Update maintainers - 2022-11-07 (#13)Contributors: Audrow Nash, Jacob Perronrqt_reconfigurereorder imports to fix flake8 warning (#129)Fixed validator locale when float value is not bound in a range. (#121)get parameter type from descriptor[rolling] Update maintainers - 2022-11-07 (#122)Cleanup mislabeled BSD license (#66)Add support for array types (#108)Fix float slider step size (#117)update maintainerFixed package to run with ros2 run (#81)fix updating range limits (#108)Improvement; “GUI hangs for awhile or completely, when any one of nodes doesn’t return any value” (#81)Contributors: Aris Synodinos, Audrow Nash, Christian Rauch, Dharini Dutia, Florian Vahl, Jacob Perron, Shrijit Singh, Tully Foote, quarkytalerqt_service_caller[rolling] Update maintainers - 2022-11-07 (#25)Contributors: Audrow Nash, Jacob Perronrqt_shell[rolling] Update maintainers - 2022-11-07 (#17)Contributors: Audrow Nash, Jacob Perronrqt_srv[rolling] Update maintainers - 2022-11-07 (#10)Contributors: Audrow Nash, Jacob Perronrqt_topic[rolling] Update maintainers - 2022-11-07 (#43)Implement bandwidth monitoring (#40)Fix the display of array type elements. (#41)Fix removal of topics while they are being monitored. (#39)Contributors: Audrow Nash, Chris Lalancette, Jacob Perronrti_connext_dds_cmake_moduleUse unified approach for checking the existence of environment variables (#117)Contributors: Christopher Wechtrttest[rolling] Update maintainers - 2022-11-07 (#121)Addressing issues found in Humble testing (#116)Contributors: Audrow Nash, Michael Carrollrviz2Make rviz1_to_rviz2.py accept configs with missing values (#945)Update rviz to C++17. (#939)[rolling] Update maintainers - 2022-11-07 (#923)Add rviz1_to_rviz2.py conversion script (#882)Contributors: Audrow Nash, Chris Lalancette, Shane Loretzrviz_assimp_vendorIf vendored assimp is present, always prefer that (#970)[rolling] Update maintainers - 2022-11-07 (#923)Fixes policy CMP0135 warning for CMake >= 3.24 (#898)Contributors: Audrow Nash, Cristóbal Arroyo, Scott K Loganrviz_commonUpdate Frame shortcut (#958) * Update Frame shortcutUpdate rviz to C++17. (#939)[rolling] Update maintainers - 2022-11-07 (#923)Remove YAML_CPP_DLL define (#831)Document getTransform() time behavior (#893)Ogre 1.12.10 upgrade (#878)Add RVIZ_COMMON_PUBLIC macro (#865)Add time jump handler (#752) (#791)Make sure not to dereference a null Renderable pointer. (#850)Contributors: Akash, Audrow Nash, Chris Lalancette, David V. Lu!!, Kenji Brameld, Marcel Zeilinger, Shane Loretz, juchajamrviz_default_pluginsFix ODR errors with gmock (#967)Update Frame shortcut (#958)point_marker: fix bug where the number of rendered points accumulates over time (#949)Update rviz to C++17. (#939)Fix tolerance calculation precision (#934)Fix MeshResourceMarker for mesh with color-based embedded material (#928)[rolling] Update maintainers - 2022-11-07 (#923)Add Map Display binary option (#846)Delete frame_locked_markers when reusing marker (#907)Consider region of interest in CameraDisplay (#864)std::copy fix - OccupancyGridUpdate - Data is not being processed correctly (#895)Set error status when duplicate markers are in the same MarkerArray (#891)Make Axes display use latest transform (#892)Show link names in inertia error message (#874)Ogre 1.12.10 upgrade (#878)Use make_shared to construct PointCloud2 (#869)Fix include order (#858)Contributors: AndreasR30, Audrow Nash, Chris Lalancette, David V. Lu!!, Eric, Hunter L. Allen, Jacob Perron, Kenji Brameld, Patrick Roncagliolo, Shane Loretz, Timon Engelke, Xavier BROQUERE, Xenofon Karamanos, methylDragonrviz_ogre_vendorFix build failures on macOS + Apple Silicon (#944)[rolling] Update maintainers - 2022-11-07 (#923)Remove broken rviz_ogre_vendor::RenderSystem_GL target (#920)Fixes policy CMP0135 warning for CMake >= 3.24 (#898)Ogre 1.12.10 upgrade (#878)Make resource file paths relative (#862)Use CMAKE_STAGING_PREFIX for staging OGRE installation (#861)Contributors: Audrow Nash, Cristóbal Arroyo, Kenji Brameld, Scott K Logan, Shane Loretz, Yadurviz_rendering[rolling] Update maintainers - 2022-11-07 (#923)add test to ensure binary STL files from SOLIDWORKS get imported without a warning (#917)Ogre 1.12.10 upgrade (#878)Stop using glsl150 resources for now. (#851)Contributors: Audrow Nash, Chris Lalancette, Kenji Brameldrviz_rendering_tests[rolling] Update maintainers - 2022-11-07 (#923)add test to ensure binary STL files from SOLIDWORKS get imported without a warning (#917)Contributors: Audrow Nash, Kenji Brameldrviz_visual_testing_frameworkUpdate rviz to C++17. (#939)[rolling] Update maintainers - 2022-11-07 (#923)Ogre 1.12.10 upgrade (#878)Contributors: Audrow Nash, Chris Lalancette, Kenji Brameldsensor_msgsupdate YUV format codes and documentation (#214)sensor_msgs/Range lacks variance field (#181)Update common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Replaced non-ASCII dash symbol with ASCII dash (#208)Add NV21 and NV24 to colour formats (#205)Update BatteryState.msg (#206)use regex for matching cv types (#202)Fix outdated file path for image_encodings (#200)Use uint32_t for pointcloud2 resize method (#195)Retain width and height after resize for master (#193)Contributors: Audrow Nash, Borong Yuan, Chris Lalancette, Christian Rauch, El Jawad Alaa, Geoffrey Biggs, Ivan Zatevakhin, Kenji Brameld, Tianyu Lisensor_msgs_pyAdd missing dep for sensor_msgs_py (#217)[rolling] Update maintainers - 2022-11-07 (#210)Add support for non standard point step sizes (#199)Remove reference to old implementation (#198)Contributors: Audrow Nash, Florian Vahl, Yaduservice_msgsUpdate common_interfaces to C++17. (#215) (#151)Add service_msgs package (#143)Contributors: Brian, Chris Lalancetteshape_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Fix SolidPrimitive.msg to contain a single Polygon (#189)Contributors: Audrow Nash, Chris Lalancette, M. Fatih Cırıtshared_queues_vendorAdd Michael Orlov as maintainer in rosbag2 packages (#1215)Fixes policy CMP0135 warning for CMake >= 3.24 (#1084)Contributors: Cristóbal Arroyo, Michael Orlovspdlog_vendorUpdate to spdlog 1.9.2 (#33)[rolling] Update maintainers - 2022-11-07 (#31)Update to spdlog 1.9.1 (#27)Fixes policy CMP0135 warning for CMake >= 3.24 (#30)build shared lib only if BUILD_SHARED_LIBS is set (#29)Mirror rolling to masterxml tag orderupdating maintainerContributors: Audrow Nash, Chris Lalancette, Cristóbal Arroyo, Dharini Dutia, Scott K Logan, hannes09sqlite3_vendorUpdate to sqlite3 3.37.2 (#1274) This matches version distributed in Ubuntu Jammy.Add Michael Orlov as maintainer in rosbag2 packages (#1215)Fixes policy CMP0135 warning for CMake >= 3.24 (#1084)Contributors: Cristóbal Arroyo, Michael Orlov, Scott K Logansros2Fix SSH commands in SROS2_Linux.md (#286)Make type of get_package_share_directory apparent for sphinx (#284)Contributors: Boris Boutillier, Yadustatistics_msgsUpdate common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)Contributors: Audrow Nash, Chris Lalancettestd_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancettestd_srvsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancettestereo_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancettetango_icons_vendor[rolling] Update maintainers - 2022-11-07 (#10)Mirror rolling to masterContributors: Audrow Nashtest_cliUpdate the system tests to C++17. (#510)[rolling] Update maintainers - 2022-11-07 (#509)Contributors: Audrow Nash, Chris Lalancettetest_cli_remappingUpdate the system tests to C++17. (#510)[rolling] Update maintainers - 2022-11-07 (#509)Contributors: Audrow Nash, Chris Lalancettetest_communicationUpdate the system tests to C++17. (#510)[rolling] Update maintainers - 2022-11-07 (#509)Revert “Replace deprecated spin_until_future_complete with spin_until_complete (#499)” (#504)Replace deprecated spin_until_future_complete with spin_until_complete (#499)Contributors: Audrow Nash, Chris Lalancette, Hubert Liberacki, William Woodalltest_interface_files[rolling] Update maintainers - 2022-11-07 (#21)Mirror rolling to masterContributors: Audrow Nashtest_launch_rosEnable document generation using rosdoc2 (#359)Fix normalize_parameters_dict for multiple nodes in the same namespace (#347)Implement None check for ComposableNodeContainer (#341)Add LifecyleTransition action (#317)Ensure load_composable_nodes respects condition (#339)[rolling] Update maintainers - 2022-11-07 (#331)RosTimer -> ROSTimer and PushRosNamespace -> PushROSNamespace, to follow PEP8 (#326)add SetROSLogDir action (#325)Support default values in parameter substitution (#313)Run condition for composable nodes (#311)Load composable nodes in sequence (#315)Contributors: Aditya Pande, Alexey Merzlyakov, Audrow Nash, Christoph Hellmann Santos, Kenji Miyake, Shane Loretz, William Woodall, Yadu, methylDragontest_launch_testing[rolling] Update maintainers - 2022-11-07 (#671)Contributors: Audrow Nashtest_msgsUpdate common_interfaces to C++17. (#215) (#151)[rolling] Update maintainers - 2022-11-07 (#150)Depend on rosidl_core_generators for packages required by actions (#144)Make the functions in the header static inline (#140)Contributors: Audrow Nash, Chris Lalancette, Jacob Perrontest_osrf_testing_tools_cppChanging C++ Compile Version (#76)Update maintainers (#74)Contributors: Audrow Nash, Lucas Wendlandtest_quality_of_serviceFix ODR errors with gtest (#514)Avoid flaky test (#513)Update the system tests to C++17. (#510)[rolling] Update maintainers - 2022-11-07 (#509)Pass rclcpp::QoS to create_service (#507)Pass rclcpp::QoS to create_client (#506)Remove Werror from test_quality_of_service. (#503)Revert “Replace deprecated spin_until_future_complete with spin_until_complete (#499)” (#504)Replace deprecated spin_until_future_complete with spin_until_complete (#499)Add tests for ‘best available’ QoS policies (#501)Contributors: Audrow Nash, Chen Lihui, Chris Lalancette, Hubert Liberacki, Jacob Perron, Shane Loretz, William Woodall, methylDragontest_rclcppUpdate the system tests to C++17. (#510)[rolling] Update maintainers - 2022-11-07 (#509)Pass rclcpp::QoS to create_service (#507)Pass rclcpp::QoS to create_client (#506)Revert “Replace deprecated spin_until_future_complete with spin_until_complete (#499)” (#504)Replace deprecated spin_until_future_complete with spin_until_complete (#499)Contributors: Audrow Nash, Chris Lalancette, Hubert Liberacki, Shane Loretz, William Woodalltest_rmw_implementationAdd tests for rmw matched event (#216)Update rmw_implementation to C++17. (#214)[rolling] Update maintainers - 2022-11-07 (#212)Add rmw_get_gid_for_client & tests (#206)Contributors: Audrow Nash, Barry Xu, Brian, Chris Lalancettetest_ros2traceMove ros2trace tests to new test_ros2trace package (#63)Contributors: Christophe Bedardtest_security[rolling] Update maintainers - 2022-11-07 (#509)Contributors: Audrow Nashtest_tf2Update the demos to C++17. (#578)Update maintainers (#560)Contributors: Audrow Nash, Chris Lalancettetest_tracetoolsDisable tracing on Android (#72)Add intra-process tracepoints (#30)Allow requiring minimum lttng package version for is_lttng_installed (#59)Disable tracing on macOS (#53)Include tracepoints by default on Linux (#31)Fix memory leak in tracetools::get_symbol() (#43)Update tracing to C++17. (#33)Contributors: Chris Lalancette, Christophe Bedard, Przemysław Dąbrowski, ymskitest_tracetools_launchError out if trace already exists unless ‘append’ option is used (#58)Make subbuffer size configurable with Trace action (#51)Allow requiring minimum lttng package version for is_lttng_installed (#59)Enable document generation using rosdoc2 for ament_python pkgs (#50)Contributors: Christophe Bedard, Christopher Wecht, Yadutf2Fix error code returned in BufferCore::walkToTopParent (#602)Depend on ament_cmake_ros to default SHARED to ON (#591)Fix a potential crash in TimeCache::findClosest (#592)Extend TimeCache API to provide rich ExtrapolationException infos (#586)Update geometry2 to C++17 (#584)Include required header Scalar.h (#559)Update maintainers (#560)Contributors: Audrow Nash, Chris Lalancette, Patrick Roncagliolo, Shane Loretz, Tyler Weavertf2_bulletUpdate the demos to C++17. (#578)Update maintainers (#560)Contributors: Audrow Nash, Chris Lalancettetf2_eigenUpdate the demos to C++17. (#578)Update maintainers (#560)Contributors: Audrow Nash, Chris Lalancettetf2_eigen_kdlUpdate geometry2 to C++17 (#584)Update maintainers (#560)Use orocos_kdl_vendor and orocos-kdl target (#534)Contributors: Audrow Nash, Chris Lalancette, Scott K Logantf2_geometry_msgsAdd do_transform_polygon_stamped (#582)Update the demos to C++17. (#578)Update maintainers (#560)Add torque due to force offset (#538)Use orocos_kdl_vendor and orocos-kdl target (#534)Contributors: Audrow Nash, Chris Lalancette, Paul Gesel, Scott K Logan, Tony Najjartf2_kdlUpdate the demos to C++17. (#578)Update maintainers (#560)Use orocos_kdl_vendor and orocos-kdl target (#534)Contributors: Audrow Nash, Chris Lalancette, Scott K Logantf2_msgsUpdate geometry2 to C++17 (#584)Update maintainers (#560)Remove action_msgs dependency (#547)Contributors: Audrow Nash, Chris Lalancette, Jacob Perrontf2_pyUpdate geometry2 to C++17 (#584)Update maintainers (#560)Contributors: Audrow Nash, Chris Lalancettetf2_rosDestroy callback group before node (#595)Enable TransformListener node-based constructor in Intra-process enabled components (#572)Fix use-after-free bug in BufferServer::cancelCB (#579)Update the demos to C++17. (#578)add constructor to static tf broadcaster accepting node interfaces (#576)Update maintainers (#560)Switching from sstream to c string formatting to fix ros arg issue (#557)allow construction of tf broadcaster from node object (not a pointer) (#555)Allow to constructTransformBroadcasterandTransformListenerfrom node interfaces (#552)Suppress spam from calling canTransform (#529)Contributors: Alberto Soragna, Alexander Hans, Audrow Nash, Chris Lalancette, Gonzo, Michael Carroll, Patrick Roncagliolotf2_ros_pyUpdate sys.path with wokring directory (#594)Enable document generation using rosdoc2 for ament_python pkgs (#587)Update maintainers (#560)Use pytest rather than unittest to enable repeat (#558)Contributors: Audrow Nash, Michael Carroll, Yadutf2_sensor_msgsUpdate the demos to C++17. (#578)Update maintainers (#560)feat: export tf2 sensor msgs target (#536)tf2_sensor_msgs find the right Python executable. (#525)Add missing ament_cmake_pytest package needed because of newly-enabled test (#520)Port point cloud transformation to numpy (#507)Contributors: Audrow Nash, Chris Lalancette, Daisuke Nishimatsu, Florian Vahl, Jorge Perez, Michael Jeronimotf2_toolsEnable document generation using rosdoc2 for ament_python pkgs (#587)Update maintainers (#560)Contributors: Audrow Nash, Yadutlsf[rolling] Update maintainers - 2022-11-07 (#13)Update maintainers (#12)Contributors: Audrow Nash, methylDragontlsf_cppUpdate realtime support to C++17. (#122)[rolling] Update maintainers - 2022-11-07 (#121)Addressing issues found in Humble testing (#116)Contributors: Audrow Nash, Chris Lalancette, Michael Carrolltopic_monitorupdate launch file name format to match documentation (#588)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Patrick Wspanialytopic_statistics_demoUpdate the demos to C++17. (#594)[rolling] Update maintainers - 2022-11-07 (#589)Contributors: Audrow Nash, Chris LalancettetracetoolsDisable tracing on Android (#72)Add intra-process tracepoints (#30)Improve tracetools rosdoc2/doxygen output (#57)Update README and other documentation (#55)Disable tracing on macOS (#53)Include tracepoints by default on Linux (#31)Explicitly link against dl for dladdr() (#48)Fix memory leak in tracetools::get_symbol() (#43)Add TRACEPOINT_ENABLED() and DO_TRACEPOINT() macros (#46)Update tracing to C++17. (#33)Add new rclcpp_subscription_init tracepoint to support new intra-process commsContributors: Chris Lalancette, Christophe Bedard, Przemysław Dąbrowski, ymskitracetools_launchError out if trace already exists unless ‘append’ option is used (#58)Improve ‘ros2 trace’ command error handling & add end-to-end tests (#54)Make subbuffer size configurable with Trace action (#51)Enable document generation using rosdoc2 for ament_python pkgs (#50)Remove deprecated context_names parameter (#38)Contributors: Christophe Bedard, Christopher Wecht, Yadutracetools_traceError out if trace already exists unless ‘append’ option is used (#58)Improve ‘ros2 trace’ command error handling & add end-to-end tests (#54)Make subbuffer size configurable with Trace action (#51)Add intra-process tracepoints (#30)Allow requiring minimum lttng package version for is_lttng_installed (#59)Include tracepoints by default on Linux (#31)Enable document generation using rosdoc2 for ament_python pkgs (#50)Replace distutils.version.StrictVersion with packaging.version.Version (#42)Remove deprecated context_names parameter (#38)Contributors: Christophe Bedard, Christopher Wecht, Yadu, ymskitrajectory_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris LalancetteturtlesimRemove the range constraints from the holonomic parameter. (#150) (#151)Add icon (#148) (#149)Update turtlesim to C++17. (#146)[rolling] Update maintainers - 2022-11-07 (#145)Add parameter to enable holonomic motion (#131)Add humble turtle (#140)Contributors: Audrow Nash, Chris Lalancette, Daisuke Sato, mergify[bot]type_description_interfacesAdd GetTypeDescription.srv (rep2011) (#153)new package and interfaces for describing other types (#146)Contributors: Emerson Knapp, William Woodallunique_identifier_msgs[rolling] Update maintainers - 2022-11-07 (#26)Depend on rosidl_core instead of rosidl_defaults (#24)Mirror rolling to masterUpdate maintainers (#22)Contributors: Audrow Nash, Jacob Perron, methylDragonurdf[rolling] Update maintainers - 2022-11-07 (#35)[urdf] package.xml: add missing exec_depend to urdf_parser_plugin (#34)Provide copy and move constructors formodel(#33)Add linter tests and fix errors (#30)fix#30Contributors: Audrow Nash, Daniel Reuter, Tobias Neumannurdf_parser_plugin[rolling] Update maintainers - 2022-11-07 (#35)Contributors: Audrow Nashvisualization_msgsUpdate common_interfaces to C++17. (#215)[rolling] Update maintainers - 2022-11-07 (#210)Contributors: Audrow Nash, Chris Lalancetteyaml_cpp_vendor[rolling] Update maintainers - 2022-11-07 (#40)Export YAML_CPP_DLL define on Windows (#30) (#38)Sets CMP0135 policy behavior to NEW (#36)Fixes policy CMP0135 warning for CMake >= 3.24 (#35)build shared lib only if BUILD_SHARED_LIBS is set (#34)Mirror rolling to masterContributors: Audrow Nash, Cristóbal Arroyo, Jacob Perron, hannes09zstd_vendorAdd Michael Orlov as maintainer in rosbag2 packages (#1215)Bump zstd to 1.4.8 in zstd_vendor package (#1132)Fix/zstd vendor does not find system zstd (#1111)Contributors: DasRoteSkelett, Michael Orlov \ No newline at end of file diff --git "a/exported_docs/ros2/Jazzy_Jalisco_changelog\357\203\201.txt" "b/exported_docs/ros2/Jazzy_Jalisco_changelog\357\203\201.txt" new file mode 100644 index 0000000..a4023fc --- /dev/null +++ "b/exported_docs/ros2/Jazzy_Jalisco_changelog\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Jazzy Jalisco changelog +URL: https://docs.ros.org/en/jazzy/Releases/Jazzy-Jalisco-Complete-Changelog.html +Section: Installation +-------------------------------------------------------------------------------- + +Jazzy Jalisco changelogThis page is a list of the complete changes in all ROS 2 core packages since the previous release.Table of Contentsaction_tutorials_cppaction_tutorials_interfacesaction_tutorials_pyactionlib_msgsament_clang_formatament_clang_tidyament_cmakeament_cmake_autoament_cmake_clang_formatament_cmake_clang_tidyament_cmake_copyrightament_cmake_coreament_cmake_cppcheckament_cmake_cpplintament_cmake_export_definitionsament_cmake_export_dependenciesament_cmake_export_include_directoriesament_cmake_export_interfacesament_cmake_export_librariesament_cmake_export_link_flagsament_cmake_export_targetsament_cmake_flake8ament_cmake_gen_version_hament_cmake_gmockament_cmake_google_benchmarkament_cmake_gtestament_cmake_include_directoriesament_cmake_librariesament_cmake_lint_cmakeament_cmake_mypyament_cmake_pclintament_cmake_pep257ament_cmake_pycodestyleament_cmake_pyflakesament_cmake_pytestament_cmake_pythonament_cmake_target_dependenciesament_cmake_testament_cmake_uncrustifyament_cmake_vendor_packageament_cmake_versionament_cmake_xmllintament_copyrightament_cppcheckament_cpplintament_flake8ament_index_cppament_index_pythonament_lintament_lint_autoament_lint_cmakeament_lint_commonament_mypyament_packageament_pclintament_pep257ament_pycodestyleament_pyflakesament_uncrustifyament_xmllintcamera_calibration_parserscamera_info_managerclass_loadercommon_interfacescompositiondemo_nodes_cppdemo_nodes_cpp_nativedemo_nodes_pydiagnostic_msgsdummy_map_serverdummy_robot_bringupdummy_sensorsexample_interfacesexamples_rclcpp_minimal_subscriberexamples_rclcpp_wait_setfoonathan_memory_vendorgeometry_msgsgoogle_benchmark_vendorgz_cmake_vendorgz_math_vendorgz_utils_vendorimage_toolsimage_transportinteractive_markersintra_process_demokdl_parserkeyboard_handlerlaser_geometrylaunchlaunch_pytestlaunch_roslaunch_testinglaunch_testing_exampleslaunch_testing_roslaunch_xmllaunch_yamllibcurl_vendorliblz4_vendorlibstatistics_collectorlibyaml_vendorlifecyclelifecycle_pylogging_demolttngpymap_msgsmcap_vendormessage_filtersmimick_vendornav_msgsorocos_kdl_vendorosrf_pycommonosrf_testing_tools_cpppendulum_controlpendulum_msgspluginlibpybind11_vendorpython_cmake_modulepython_orocos_kdl_vendorpython_qt_bindingqt_dotgraphqt_guiqt_gui_cppquality_of_service_demo_cppquality_of_service_demo_pyrclrcl_actionrcl_interfacesrcl_lifecyclercl_logging_interfacercl_logging_nooprcl_logging_spdlogrcl_yaml_param_parserrclcpprclcpp_actionrclcpp_componentsrclcpp_lifecyclerclpyrcpputilsrcutilsresource_retrieverrmwrmw_connextddsrmw_connextdds_commonrmw_connextddsmicrormw_cyclonedds_cpprmw_dds_commonrmw_fastrtps_cpprmw_fastrtps_dynamic_cpprmw_fastrtps_shared_cpprmw_implementationrobot_state_publisherros2actionros2bagros2cliros2cli_test_interfacesros2componentros2doctorros2interfaceros2paramros2pkgros2serviceros2topicros2tracerosbag2_compressionrosbag2_compression_zstdrosbag2_cpprosbag2_examples_cpprosbag2_examples_pyrosbag2_interfacesrosbag2_performance_benchmarkingrosbag2_pyrosbag2_storagerosbag2_storage_mcaprosbag2_storage_sqlite3rosbag2_test_commonrosbag2_test_msgdefsrosbag2_testsrosbag2_transportrosidl_cmakerosidl_dynamic_typesupportrosidl_generator_crosidl_generator_cpprosidl_generator_dds_idlrosidl_generator_pyrosidl_generator_testsrosidl_generator_type_descriptionrosidl_parserrosidl_pycommonrosidl_runtime_crosidl_runtime_cpprosidl_runtime_pyrosidl_typesupport_crosidl_typesupport_cpprosidl_typesupport_fastrtps_crosidl_typesupport_fastrtps_cpprosidl_typesupport_introspection_crosidl_typesupport_introspection_cpprosidl_typesupport_introspection_testsrosidl_typesupport_testsrpyutilsrqtrqt_bagrqt_bag_pluginsrqt_consolerqt_graphrqt_gui_cpprqt_gui_pyrqt_msgrqt_plotrqt_publisherrqt_py_commonrqt_py_consolerqt_reconfigurerqt_service_callerrqt_shellrqt_srvrqt_topicrti_connext_dds_cmake_modulerttestrviz2rviz_assimp_vendorrviz_commonrviz_default_pluginsrviz_ogre_vendorrviz_renderingrviz_rendering_testsrviz_visual_testing_frameworksensor_msgssensor_msgs_pyshape_msgsshared_queues_vendorspdlog_vendorsqlite3_vendorsros2std_msgsstd_srvsstereo_msgstest_clitest_cli_remappingtest_communicationtest_launch_rostest_launch_testingtest_msgstest_quality_of_servicetest_rclcpptest_rmw_implementationtest_ros2tracetest_securitytest_tf2test_tracetoolstest_tracetools_launchtf2tf2_bullettf2_eigentf2_eigen_kdltf2_geometry_msgstf2_kdltf2_pytf2_rostf2_ros_pytf2_sensor_msgstf2_toolstopic_monitortopic_statistics_demotracetoolstracetools_launchtracetools_readtracetools_testtracetools_tracetrajectory_msgsturtlesimuncrustify_vendorunique_identifier_msgsurdfurdf_parser_pluginvisualization_msgsyaml_cpp_vendorzstd_vendoraction_tutorials_cppUpdate maintainer list in package.xml files (#665)Fix format-security warning with clang. (#663)Migrate std::bind calls to lambda expressions (#659)Contributors: Chris Lalancette, Felipe Gomes de Melo, Michael Jeronimoaction_tutorials_interfacesUpdate maintainer list in package.xml files (#665)Contributors: Michael Jeronimoaction_tutorials_pyUpdate maintainer list in package.xml files (#665)Add tests to action_tutorials_py. (#664)Contributors: Chris Lalancette, Michael Jeronimoactionlib_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancetteament_clang_formatUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_clang_tidyUpdate maintainer list in package.xml files (#474)Fix a warning from newer versions of flake8. (#469)remove AMENT_IGNORE check in clang-tidy when looking for compilation db (#441)Contributors: Alberto Soragna, Chris Lalancette, Michael Jeronimoament_cmakeUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_autoUpdate maintainer list in package.xml files (#503)Add ament_auto_add_gmock to ament_cmake_auto (#482)Contributors: Jordan Palacios, Michael Jeronimoament_cmake_clang_formatUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_clang_tidyUpdate maintainer list in package.xml files (#474)Provide –header-filter and –jobs to CMake. (#450)Contributors: Michael Jeronimo, Roderick Taylorament_cmake_copyrightUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_coreSet hints to find the python version we actually want. (#508)Update maintainer list in package.xml files (#503)Use CMAKE_CURRENT_BINARY_DIR instead of CMAKE_BINARY_DIR in ament_generate_environment (#485)Fix CMake error when entire ament projects are added via add_subdirectory (#484)Contributors: Chris Lalancette, Michael Jeronimo, Silvio Traversaroament_cmake_cppcheckUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_cpplintIncreased cpplint timeout by default on Windows (#486)Update maintainer list in package.xml files (#474)Contributors: Alejandro Hernández Cordero, Michael Jeronimoament_cmake_export_definitionsUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_export_dependenciesUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_export_include_directoriesUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_export_interfacesUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_export_librariesUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_export_link_flagsUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_export_targetsUpdate maintainer list in package.xml files (#503)Add NAMESPACE support to ament_export_targets (#498)Contributors: Michael Jeronimo, Ryanament_cmake_flake8Update maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_gen_version_hUpdate maintainer list in package.xml files (#503)Update to C++17 (#488)Contributors: Chris Lalancette, Michael Jeronimoament_cmake_gmockUpdate maintainer list in package.xml files (#503)Split ament_add_gmock into _executable and _test. (#497)Contributors: Chris Lalancette, Michael Jeronimoament_cmake_google_benchmarkUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_gtestUpdate maintainer list in package.xml files (#503)Split ament_add_gmock into _executable and _test. (#497)ament_add_gtest_test: add TEST_NAME parameter (#492)Contributors: Chris Lalancette, Christopher Wecht, Michael Jeronimoament_cmake_include_directoriesUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_librariesperf: faster ament_libraries_deduplicate implementation (#448) Co-authored-by: Scott K Logan Subtle fix for ament_libraries_deduplicate tests (#516)Add some basic tests to ament_cmake_libraries (#512)Update maintainer list in package.xml files (#503)Contributors: Michael Jeronimo, Scott K Logan, Vincent Richardament_cmake_lint_cmakeUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_mypyUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_pclintUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_pep257Update maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_pycodestyleUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_pyflakesUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_cmake_pytestUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_pythonAdd in a comment explaining where Python3::Interpreter comes from. (#510)Update maintainer list in package.xml files (#503)Contributors: Chris Lalancette, Michael Jeronimoament_cmake_target_dependenciesUpdate maintainer list in package.xml files (#503)Fixament_target_dependencies(#452)Contributors: Michael Jeronimo, Vincent Richardament_cmake_testUpdate maintainer list in package.xml files (#503)Recursively check for errors/failures in produced JUnit result XMLs (#446)Contributors: Michael Jeronimo, Nick Moralesament_cmake_uncrustifyAdded Timeout to ament_uncrustify (#485)Update maintainer list in package.xml files (#474)Contributors: Alejandro Hernández Cordero, Michael Jeronimoament_cmake_vendor_packageAdd more CMake variables to pass to vendor projects (#519)Fix patch file dependencies in ament_cmake_vendor_package (#520)Update maintainer list in package.xml files (#503)Always set CMAKE_C[XX]_COMPILER for vendor packages if needed (#476)Switch to CMake ‘braket arguments’ (#461)Replace ‘git’ dep with ‘vcstool’ (#462)Add support for specifying a patch directory in ament_vendor (#449)Contributors: Christophe Bedard, Michael Jeronimo, Scott K Loganament_cmake_versionUpdate maintainer list in package.xml files (#503)Contributors: Michael Jeronimoament_cmake_xmllintUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_copyrightSmall fixes for modern flake8. (#484)Fix add-copyright year function (#466)Update maintainer list in package.xml files (#474)Contributors: Chris Lalancette, Lloyd Pearson, Michael Jeronimoament_cppcheckUpdate maintainer list in package.xml files (#474)Add in checks to ament_cppcheck code. (#472)Contributors: Chris Lalancette, Michael Jeronimoament_cpplintUpdate maintainer list in package.xml files (#474)Pass –output argument to cpplint (#453)Contributors: Michael Jeronimo, Vladimir Ivanament_flake8Update maintainer list in package.xml files (#474)Changes to make ament_flake8 work with v6+ (#459)Add additional dependencies to ament_flake8. (#454)Fix compatibility with flake8 version 5 (#410)Contributors: Chris Lalancette, Michael Carroll, Michael Jeronimo, Timo Röhlingament_index_cppUpdate quality declaration documents (#94)only append search paths on first PackageNotFound (#91)Update to C++17 (#90)Contributors: Chris Lalancette, Christophe Bedard, Lucas Walterament_index_pythonUpdate quality declaration documents (#94)Add type annotations to python files. (#93)Contributors: Christophe Bedard, Michael Carlstromament_lintUpdate maintainer list in package.xml files (#474)Add an ament_lint test dependency on python3-pytest. (#473)Contributors: Chris Lalancette, Michael Jeronimoament_lint_autoUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_lint_cmakeUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_lint_commonUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_mypyUpdate maintainer list in package.xml files (#474)Fix a flake8 warning in ament_mypy. (#470) No need for parentheses around an assert.Contributors: Chris Lalancette, Michael Jeronimoament_packageMigrate from legacy importlib-resources (#143)Add setuptools dependency back in. (#141)Make python dependencies exec_depend. (#140)Contributors: Chris Lalancette, Isabel Paredesament_pclintUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_pep257Update maintainer list in package.xml files (#474)Convert linenumber to string when printing errors (#443)Contributors: Michael Jeronimo, Robert Brothersament_pycodestyleUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_pyflakesUpdate maintainer list in package.xml files (#474)Contributors: Michael Jeronimoament_uncrustifyAdds uncrustify 0.78.1 config (#475)Update maintainer list in package.xml files (#474)Fix a flake8 warning in ament_uncrustify. (#471)Contributors: Chris Lalancette, Marco A. Gutierrez, Michael Jeronimoament_xmllintUpdate maintainer list in package.xml files (#474)(ament_xmllint) add extensions argument (#456)Contributors: Matthijs van der Burgh, Michael Jeronimocamera_calibration_parsersUpdate to yaml-cpp 0.8.0. (#305)Switch from rcpputils::fs to std::filesystem (#300)Removed C headers: camera_info_manager camera_calibration_parsers (#290)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Christophe Bedardcamera_info_managerSwitch from rcpputils::fs to std::filesystem (#300)Removed C headers: camera_info_manager camera_calibration_parsers (#290)Contributors: Alejandro Hernández Cordero, Christophe Bedardclass_loaderRemove all uses of ament_target_dependencies. (#210)Update to C++17 (#209)Contributors: Chris Lalancettecommon_interfacesClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancettecomposition[composition] add launch action console output in the verify section (#677) (#681) (cherry picked from commit 34d29db73e78a84a174ad8699a2d646b0eeb1cdf) Co-authored-by: Mikael Arguedas Update maintainer list in package.xml files (#665)Migrate std::bind calls to lambda expressions (#659)Contributors: Felipe Gomes de Melo, Michael Jeronimo, mergify[bot]demo_nodes_cpp[demo_nodes_cpp] some readme and executable name fixups (#678) (#688) (cherry picked from commit aa8df8904b864d063e31fd5b953ffe561c7a9fe0) Co-authored-by: Mikael Arguedas Fix gcc warnings when building with optimizations. (#672) (#673) * Fix gcc warnings when building with optimizations. When building the allocator_tutorial_pmr demo with -O2, gcc is throwing an error saying that new and delete are mismatched. This is something of a misnomer, however; the real problem is that the global new override we have in that demo is actually implemented incorrectly. In particular, the documentation athttps://en.cppreference.com/w/cpp/memory/new/operator_newvery clearly specifies that operator new either has to return a valid pointer, or throw an exception on error. Our version wasn’t throwing the exception, so change it to throw std::bad_alloc if std::malloc fails. While we are in here, also fix another small possible is where std::malloc could return nullptr on a zero-sized object, thus throwing an exception it shouldn’t. * Always inline the new and delete operators. That’s because gcc 13 has a bug where it can sometimes inline one or the other, and then it detects that they mismatch. For gcc and clang, just force them to always be inline in this demo. * Switch to NOINLINE instead. Both clang and MSVC don’t like inlining these, so instead ensure that they arenotinlined. This also works because the problem is when new is inlined but not delete (or vice-versa). As long as they are both not inlined, this should fix the warning. (cherry picked from commit 957ddbb9f04f55cabd8496e8d74eb35ee4d29105) Co-authored-by: Chris Lalancette A few uncrustify fixes for 0.78. (#667)Allow users to configure the executor for executables indemo_nodes_cpp(#666)Update maintainer list in package.xml files (#665)Added extra documentation and clarifications. (#651)Add in support for both the PMR and custom allocator tutorials. (#655)Replacing old-style C++ allocator with a polymorphic memory resource (PMR) (#653)Remove unnecessary captures in the various demos. (#647)Dramatically speed up the demo_nodes_cpp tests (#641)Switch to using RCLCPP logging macros in the lifecycle package. (#644)failed to call introspection_client (#643)Small cleanups to the demos when running through them. (#639)Cleanup demo_nodes_cpp CMake and dependencies (#638)Change the service introspection parameter off value to ‘disabled’ (#634)Add demos for using logger service (#611)Contributors: Ali Ashkani Nia, Barry Xu, Chen Lihui, Chris Lalancette, Michael Jeronimo, Yadu, jrutgeer, mergify[bot]demo_nodes_cpp_nativeUpdate maintainer list in package.xml files (#665)Contributors: Michael Jeronimodemo_nodes_pyUpdate maintainer list in package.xml files (#665)Change the service introspection parameter off value to ‘disabled’ (#634) With this we can avoid the tricky bits around YAML interpretation of ‘off’ as a boolean.Add demos for using logger service (#611)Contributors: Barry Xu, Chris Lalancette, Michael Jeronimodiagnostic_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancettedummy_map_serverUpdate maintainer list in package.xml files (#665)Contributors: Michael Jeronimodummy_robot_bringupUpdate maintainer list in package.xml files (#665)Switch to file-content launch substitution (#627)Contributors: Michael Jeronimo, Scott K Logandummy_sensorsUpdate dummy_sensors readme to echo the correct topic (#675) (#684) (cherry picked from commit eec5c12ea95dfaaa230f9f1a8e9cff9b09dde5d5) Co-authored-by: jmackay2 <1.732mackay@gmail.com>Update maintainer list in package.xml files (#665)Fix unstable LaserScan status for rviz2 (#614)Contributors: Chen Lihui, Michael Jeronimo, mergify[bot]example_interfacesUpdate to C++17. (#18)Contributors: Chris Lalancetteexamples_rclcpp_minimal_subscriberfix: Fixed compilation after API change of TimerBase::execute (#375) Co-authored-by: Janosch Machowinski Split lambda and subscriber def in minimal example (#363)Contributors: Felipe Gomes de Melo, jmachowinskiexamples_rclcpp_wait_setfix: Fixed compilation after API change of TimerBase::execute (#375) Co-authored-by: Janosch Machowinski Contributors: jmachowinskifoonathan_memory_vendorImprove mechanism to find an installation of foonathan_memory (#67)Added support for QNX 7.1 build (#65)geometry_msgsRemove references to index.ros.org. (#244)Create new messages with all fields needed to define a velocity and transform it (#240) Co-authored-by: Dr. Denis Co-authored-by: Addisu Z. Taddese Co-authored-by: Tully Foote Clarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).adding IDs to geometry_msgs/Polygon, PolygonStamped (#232)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Steve Macenskigoogle_benchmark_vendorUpdate to 1.8.3. (#29)Contributors: Marco A. Gutierrezgz_cmake_vendorUpdate vendored version to 3.5.3Use an alias target for root libraryAdd support for the::and::alltargets, fix sourcing of dsv filesUpdate vendored version to 3.5.2Update vendored package versionPatch the pkg-config directory in the gz-cmake code. (#4) * Patch the pkg-config directory in the gz-cmake code. When building on the ROS 2 buildfarm, we aren’t setting some of the CMAKE_PREFIX variables. This means that using CMAKE_INSTALL_FULL_LIBDIR actually creates a path like /opt/ros/rolling/… , which makes debuild upset. However, we actually need the FULL_LIBDIR in order to calculate the relative path between it and the INSTALL_PREFIX. Work around this by having two variables; the pkgconfig_install_dir (relative), used to install the files, and pkgconfig_abs_install_dir (absolute), used to calculate the relative path between them. This should fix the build on the buildfarm. I’ll note that we are doing it here and not in gz-cmake proper because of knock-on effects to downstream gazebo. If this is successful we may end up merging it there, at which point we can drop this patch. * Update GzPackage as well. ———Require calling find_package on the underlying package (#3) This also changes the version of the vendor package to 0.0.1 and adds the version of the vendored package in the descriptionFix linter (#2)Useon upstream package so that dependency is exportedUpdate maintainerAdd package.xml and CMakeLists (#1)Initial importContributors: Addisu Z. Taddese, Chris Lalancettegz_math_vendorUse an alias target for root libraryAdd support for the::and::alltargets, fix sourcing of dsv filesDisable SWIG to fix CMake warningDisable pybind11 for nowRequire calling find_package on the underlying package (#2)Fix linter (#1)Remove NateUpdate maintainersInitial importContributors: Addisu Z. Taddesegz_utils_vendorUse an alias target for root libraryAdd support for the::and::alltargets, fix sourcing of dsv filesRequire calling find_package on the underlying package (#2)Fix linter (#1)Initial importContributors: Addisu Z. Taddeseimage_toolsA few uncrustify fixes for 0.78. (#667)Update maintainer list in package.xml files (#665)Migrate std::bind calls to lambda expressions (#659)Contributors: Chris Lalancette, Felipe Gomes de Melo, Michael Jeronimoimage_transportAdded rclcpp component to Republish (#275)Add QoS option reliability to republisher qos params (#296)implement CameraSubscriber::getNumPublishers (#297)Add missing definition for CameraPublisher::publish overload (#278)Advertize and subscribe with custom qos (#288)Removed C headers (#289)Switch to using the override keyword for simple_publisher_plugin. (#285)feat: enable plugin allowlist (#264)Expose option to set callback groups (#274)add support for lazy subscribers (#272)Contributors: Aditya Pande, Alejandro Hernández Cordero, Carlos Andrés Álvarez Restrepo, Chris Lalancette, Daisuke Nishimatsu, Michael Ferguson, s-hallinteractive_markersShorten the length of a lambda. (#106)Fixed C++20 warning that ‘++’ expression of ‘volatile’-qualified type is deprecated (#102)Cleanup of interactive markers (#101)Contributors: AiVerisimilitude, Chris Lalancetteintra_process_demoUpdate maintainer list in package.xml files (#665)Migrate std::bind calls to lambda expressions (#659)Fix executable name in README (#618)Contributors: Felipe Gomes de Melo, Michael Jeronimo, Yadunundkdl_parserUpdate to C++17. (#82)Contributors: Chris Lalancettekeyboard_handlerShorten lambdas so newer uncrustify is happier. (#42)Fixed C++20 warning implicit capture of this in lambda (#41)Update to C++17. (#37)Contributors: AiVerisimilitude, Chris Lalancettelaser_geometrySwitch to target_link_libraries. (#92)Contributors: Chris Lalancettelaunch(launch) fix describe of PathJoinSubstitution (#771)Small fixes for modern flake8. (#772)Cleanup some type annotations.Rework task exceptions loop. (#755)add format overriding by environment variables (#722)Add exception type to error output (#753)Let XML executables/nodes be “required” (like in ROS 1) (#751)Add conditional substitution (#734)Add maximum times for a process to respawn (#696)Add in a timeout for launch pytests. (#725)Fix remaining occurrences of “There is no current event loop” (#723)Update the launch code for newer flake8 and mypy. (#719)Remove the deprecated some_actions_type.py (#718)Improve launch file parsing error messages (#626)Add file-content launch substitution (#708)Contributors: Chris Lalancette, David Yackzan, Marc Bestmann, Matthew Elwin, Matthijs van der Burgh, Nick Lamprianidis, Santti4go, Scott K Logan, Timon Engelkelaunch_pytestSwitch tryfirst/trylast to hookimpl.Contributors: Chris Lalancettelaunch_rosFix: typing. Iterable doesn’t have __getitem__ (#393)Cleanup some type annotations. (#392)Create py.typed to mark this library as typed (#379)Remove create_future implementation. (#372)cache lookup of importlib metadata in Node action (#365)Get rid of unnecessary checks in composable_node_container. (#364)Contributors: Chris Lalancette, Jonas Otto, Matthijs van der Burgh, William Woodalllaunch_testingFix a warning in modern unittest. (#773) Newer versions of unittest no longer store an errors list; instead, they store a result, which then stores an error list. Update the code here to be able to deal with either version.Add consider_namespace_packages=False (#766)to open expected outpout file with an encoding parameter (#717)Contributors: Chen Lihui, Chris Lalancette, Tony Najjarlaunch_testing_examplesCleanup the launch_testing_examples. (#374)Refactor WaitForNodes class. (#373)Contributors: Chris Lalancettelaunch_testing_rosMake launch_testing_ros examples more robust. (#394)added type hinting to launch_testing_ros/test/examples (#386)Handle spin() ExternalShutdownException. (#378)Increase the timeout in wait_for_topic_launch_test. (#377)WaitForTopics: get content of messages for each topic (#353)Contributors: Chris Lalancette, Giorgio Pintaudi, Yaswanthlaunch_xmllaunch_xml: fix xml syntax in README (#770)Let XML executables/nodes be “required” (like in ROS 1) (#751) * Let XML nodes be “required” Essentially on_exit=”shutdown” is equivalent to ROS 1 required=”true”. This feature is implemented using the python launchfile on_exit mechanism. Right now “shutdown” is the only action accepted by on_exit, but theoretically more “on_exit” actions could be added later. Example: * Added tests for yamlImprove launch file parsing error messages (#626)Contributors: Matthew Elwin, Steve Peters, Timon Engelkelaunch_yamlFix flake8 warnings in launch_yaml. (#756)Let XML executables/nodes be “required” (like in ROS 1) (#751) * Let XML nodes be “required” Essentially on_exit=”shutdown” is equivalent to ROS 1 required=”true”. This feature is implemented using the python launchfile on_exit mechanism. Right now “shutdown” is the only action accepted by on_exit, but theoretically more “on_exit” actions could be added later. Example: * Added tests for yamlImprove launch file parsing error messages (#626)Contributors: Chris Lalancette, Matthew Elwin, Timon Engelkelibcurl_vendorAdd “lib” to the Windows curl search path. (#96) (#97) In CMake 3.3, a commit made it so that the find_package module in CMake had a compatibility mode where it would automatically search for packages in a /lib subdirectory. In CMake 3.6, this compatibility mode was reverted for all platformsexceptWindows. That means that since CMake 3.3, we haven’t actually been using the path as specified incurl_DIR, but we have instead been inadvertently relying on that fallback behavior. In CMake 3.28, that compatibilty mode was also removed for Windows, meaning that we are now failing to find_package(curl) in downstream packages (like resource_retriever). Fix this by adding in the “lib” directory that always should have been there. I’ll note that thisonlyaffects our Windows builds, because this code is in a if(WIN32) block. (cherry picked from commit 1839d583190eb9dcf339eaaf6bebe632d94664a6) Co-authored-by: Chris Lalancette Switch to ament_cmake_vendor_package (#86)Contributors: Scott K Logan, mergify[bot]liblz4_vendorMake sure to build_export_depend liblz4-dev. (#1614)Switch to using ament_vendor_package for lz4. (#1583)Contributors: Chris Lalancettelibstatistics_collectorBump pascalgn/automerge-action from 0.16.2 to 0.16.3Bump codecov/codecov-action from 4.1.1 to 4.2.0Fixes for newer uncrustify. (#186)Bump actions/upload-artifact from 3 to 4Switch to using target_link_libraries everywhere. (#174)Bump rolling to 1.6.3 (#173)Bump actions/checkout from 3 to 4 (#169)Add API to use message_info instead unserialized message (#170)Bump codecov/codecov-action from 3.1.3 to 3.1.4Bump actions/checkout from 3 to 4 (#169)Add API to use message_info instead unserialized message (#170)Bump codecov/codecov-action from 3.1.3 to 3.1.4Add in missing cstdint include. (#165)Bump codecov/codecov-action from 3.1.2 to 3.1.3Contributors: Chris Lalancette, Lucas Wendland, Michael Orlov, dependabot[bot]libyaml_vendorUpdate quality declaration documents (#62)remove rcpputils and rcutils dependency (#61)Set to C++17. (#59)Switch to ament_cmake_vendor_package (#58)Contributors: Chris Lalancette, Christophe Bedard, Kenta Yonekura, Scott K LoganlifecycleA few uncrustify fixes for 0.78. (#667)Update maintainer list in package.xml files (#665)Migrate std::bind calls to lambda expressions (#659)Switch to using RCLCPP logging macros in the lifecycle package. (#644)Contributors: Chris Lalancette, Felipe Gomes de Melo, Michael Jeronimolifecycle_pyUpdate maintainer list in package.xml files (#665)Contributors: Michael Jeronimologging_demoUpdate maintainer list in package.xml files (#665)Migrate std::bind calls to lambda expressions (#659)Contributors: Felipe Gomes de Melo, Michael JeronimolttngpyReplace all occurences of index.ros.org (#114)Fixes for newer uncrustify (#101)Fix Python not being found for lttngpy in Windows debug mode (#87)Switch to custom lttng-ctl Python bindings (#81)Contributors: Chris Lalancette, Christophe Bedardmap_msgsUpdate maintainer list in package.xml filesUpdate to C++17Contributors: Chris Lalancette, Michael Jeronimo, Steve Macenskimcap_vendorSwitch to using ament_vendor_package for lz4. (#1583)Switch to target_link_libraries everywhere. (#1504)Update mcap to v1.1.0 (#1361)Contributors: Chris Lalancette, Emerson Knappmessage_filtersUpdate TimeSynchronizer usage example. (#115)Remove ‘using’ keyword in message_filters (#106)Remove the use of ament_target_dependencies. (#105)Fixes pointed out by clang (#104)Mark subscription cb parameter const (#103)Update the HasHeader check to be more specific. (#101)TypeAdapters support (#95) (#96)Cleanup a few minor things in the filters. (#100)Fix python examples (#99)feat: add signal time functions to ExactTime policy (#94)Contributors: Chris Lalancette, Patrick Roncagliolo, Ricardo de Azambuja, Russ, rkeating-plantedmimick_vendorBump vendored mimick version forros2/Mimick#32(#35)Update to the commit that fixes mmk_noreturn. (#34)Update to the commit the fixes exe stack on macOS. (#33)Update to the comment that fixes the executable stack. (#32)Update to take advantage of TARGET_ARCH (#28)Switch to ament_cmake_vendor_package (#31)Contributors: Chris Lalancette, Michael Carroll, Scott K Logannav_msgsRemoved TODO (#243)Clarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Alejandro Hernández Cordero, Chris Lalancetteorocos_kdl_vendorEnsure that orocos_kdl_vendor doesn’t accidentally find itself. (#27) (#28) When initially building the orocos_kdl_vendor package (on platforms where it actually builds), it turns out that it places a valid cmake configuration in the build directory. In turn, that means that a subsequent rebuild will find this configuration in the build directory, and throw the rest of the logic off. This only seems to be a problem with CMake 3.29 and later, though I can’t say exactly why at the moment. Workaround this problem by writing the configuration out to a temporary file, and then moving it into the final place with the final name. (cherry picked from commit 7aad6d1ad9fa54f3a48f1f194a85127e362c8ade) Co-authored-by: Chris Lalancette Update to the latest orocos_kdl_kinematics commit. (#25)Switch to ament_cmake_vendor_package (#20)Contributors: Chris Lalancette, Scott K Logan, mergify[bot]osrf_pycommonCatch all of the spurious warnings from get_event_loop. (#94)Add bookworm as a python3 target (#91)Suppress warning for specifically handled behavior (#87)Update supported platforms (#93)Add GitHub Actions CI workflow (#88)Contributors: Chris Lalancette, Scott K Logan, Tully Footeosrf_testing_tools_cppUpgrade to Google test 1.14.0 (#84)Contributors: Chris Lalancettependulum_controlUpdate maintainer list in package.xml files (#665)[pendulum_control Install targets to project lib (#624)Contributors: Michael Jeronimo, Yadupendulum_msgsUpdate maintainer list in package.xml files (#665)Contributors: Michael JeronimopluginlibSwitch from rcpputils::fs to std::filesystem (#254)Remove redundant throw of a std::runtime_error (#232)Update to C++17 (#251)Fix wShadow compile warning (#250)Contributors: Chris Lalancette, Christophe Bedard, Hunter L. Allen, Steve Macenskipybind11_vendorUpdate to pybind11 2.11.1 (#28)Add Apache 2.0 LICENSE file (#27)Switch to ament_cmake_vendor_package (#24)Contributors: Chris Lalancette, Michael Carroll, Scott K Loganpython_cmake_moduleUse FindPython3 instead of FindPythonInterp (#7)Contributors: Shane Loretzpython_orocos_kdl_vendorUpdate to the latest orocos_kdl_kinematics commit. (#25)Contributors: Chris Lalancettepython_qt_bindingSuppress warning from Shiboken2. (backport#137) (#138) Co-authored-by: Chris Lalancette Co-authored-by: Alejandro Hernández Cordero Switch to C++17 for SIP and Shiboken (#135)Set hints to find the python version we actually want. (#134)Remove unnecessary parentheses around assert. (#133)Switch to FindPython3 in the shiboken_helper.cmake. (#132)Cleanup of the sip_configure.py file. (#131)Update the SIP support so we can deal with a broken RHEL-9. (#129)Contributors: Chris Lalancette, Christophe Bedard, mergify[bot]qt_dotgraphHandle empty dotcode nodes. (#290)Small fix for modern flake8. (#289)Contributors: Chris Lalancetteqt_guiRemove unnecessary parentheses for assert. (#286)(qt_gui) extended theme logic to get icons (#279)Contributors: Chris Lalancette, Matthijs van der Burghqt_gui_cppSwitch from rcpputils::fs to std::filesystem (#288)Set hints to find the python version we actually want. (#287)Update to C++17 (#278)fix unload warning (#274)Contributors: Chen Lihui, Chris Lalancette, Christophe Bedardquality_of_service_demo_cppUpdate maintainer list in package.xml files (#665)Explicit time conversion (#657)Cleanup the interactive quality of service demos. (#637)More quality of service demo cleanup (#632)Fix small typos in the incompatible_qos demos. (#629)Contributors: AiVerisimilitude, Chris Lalancette, Michael Jeronimoquality_of_service_demo_pyUpdate maintainer list in package.xml files (#665)More quality of service demo cleanup (#632)Fix small typos in the incompatible_qos demos. (#629)Fix the quality_of_service_demo_py output to look like the C++ one. (#626)Use non-deprecated rclpy import. (#615)Contributors: Chris Lalancette, Michael JeronimorclFix up rmw_cyclonedds timestamp testing. (#1156) (#1157) We are about to fix it so that rmw_cyclonedds has receive_timestamp support, so we also need to enable that support here in rcl. We actually rewrite the logic a bit because now the only combination that doesn’t work is rmw_connextdds on Windows. (cherry picked from commit 6d53d24a863c3e9e4a41e9fe5f550271210d9d9d) Co-authored-by: Chris Lalancette Fixed warnings - strict-prototypes (#1148) (#1150)chore: Minor style improvements (#1147) Co-authored-by: Janosch Machowinski improved rcl_wait in the area of timeout computation and spurious wakeups (#1146) Added special handling for timers with a clock that has time override enabled. For these timer we should not compute a timeout, as the waitset is waken up by the associated guard condition. Before this change, the waitset could wait up, because of an expected ready timer, that was acutally not ready, as the time update to the ROS_TIME had not yet arrived.Add tracepoint for publish_serialized_publish (#1136) * Add tracepoint for publish_serialized_publish * Add: tracepoint for rcl_take_serialized_message ———Revert “improved rcl_wait in the area of timeout computation and spurious wakeups (#1135)” (#1142) This reverts commit 3c6c5dc47dac23d70722a60b2c0a387d2e71b71d.improved rcl_wait in the area of timeout computation and spurious wakeups (#1135) * feat: Allow usage of rcl_timer_clock with const rcl_timer_t* * fix: Fixed purious wake-ups on ROS_TIME timers with ROS_TIME enabled Added special handling for timers with a clock that has time override enabled. For theses timer we should not compute a timeout, as the waitset is waken up by the associated guard condition. Before this change, the waitset could wait up, because of an expected ready timer, that was acutally not ready, as the time update to the ROS_TIME had not yet arrived. * feat: Added rcl_timer_get_next_call_time * fix(rcl_wait): Improved timeout computation in case of many timers This commit changes the computation of the timer timeout, to be more precise, in the case, of many registered timers. ——— Co-authored-by: Janosch Machowinski Generate version header using ament_generate_version_header(..) (#1141)Add rcl_timer_call_with_info function that retrieves the expected and the actual timer trigger times (#1113) Co-authored-by: Alexis Tsogias Co-authored-by: Michael Carroll Co-authored-by: Tomoya Fujita document out parameters for rcl_get_node_names and rcl_get_node_names_with_enclaves (#1137) * document out params for rcl_get_node_names Co-authored-by: Chris Lalancette Cleanups for uncrustify 0.78. (#1134) Mostly this is expanding macros, as this is just easier to read anyway. But we also mark one section as INDENT-OFF.Re-order rcl_logging_interface include (#1133)Remove unnecessary macros. (#1132) These really don’t add anything, and allows us to avoid some changes in macro formatting between Ubuntu 22.04 and Ubuntu 24.04.Update quality declaration documents (#1131)add unit tests for –log-file-name argument. (#1130)support--log-file-nameto ros args. (#1127)Make sure to disable a test_node test on RHEL. (#1124)remove static function rcl_ret_from_rcutils_ret(). (#1122)Remove AMENT_DEPENDENCIES from rcl_add_custom_gtest. (#1119)Remove unncecessary dependencies in tests (#1114)a rosout publisher of a node might not exist (#1115)Set disable loan to on by default. (#1110)Return service from node_type_description_service_init (#1112)next_call_time will always be greater than now after calling rcl_timer_call. (#1089)Add rcl count clients, servicec & tests (#1011)Improve the reliability of test_get_type_description_service. (#1107)Remove most remaining uses of ament_target_dependencies. (#1102)Just remove rcpputils::fs dependency (#1105)Decouple rosout publisher init from node init. (#1065)Cleanup the error handling in rcl_node_init. (#1099)Fix a clang warning for suspicious string concatentation. (#1101)add the link to the topic name rules. (#1100)Cut down the amount of time for test_logging_rosout. (#1098)Simplify local_namespace handling in rcl_node_init. (#1097)Reduce the number of tests we run (#1096)Adding duplicate node information (#1088)Revamp the test_get_type_description_service. (#1095)Cleanup network flow endpoints test. (#1094)Reduce the failure timeout time for namespaces. (#1093)Shorten wait time for a subscription not being ready. (#1092)rcl_send_response returns RCL_RET_TIMEOUT. (#1048)Move test_namespace into the correct directory. (#1087)Reset errors in tests to reduce warnings (#1085)Cleanup error reporting in the type hash code. (#1084)Instrument loaned message publication code path (#1083)Add~/get_type_descriptionservice (rep2011) (#1052)Modifies timers API to select autostart state (#1004)test publisher/subscription with the c/cpp typesupport for test_msgs::msg::array (#1074)validation result should be used to print the error message. (#1077)improve error msg ofrcl_expand_topic_name(#1076)Use TRACETOOLS_ prefix for tracepoint-related macros (#1058)fix comment (#1073)localhost_only prevails auto discovery options if enabled. (#1069)Avoid dynamic allocation of message before sending over rosout (#1067)clarifyrcl_node_initreturn code (#1066)Fix a format-security warning when building with clang. (#1064)Contributors: Chen Lihui, Chris Lalancette, Christophe Bedard, Christopher Wecht, Eloy Briceno, Eric W, Felix Penzlin, G.A. vd. Hoorn, Hans-Joachim Krauch, Kenta Yonekura, Lee, Lucas Wendland, Michael Carroll, Minju, Thiemo Kohrt, Tomoya Fujita, h-suzuki-isp, jmachowinski, mergify[bot]rcl_actionGenerate version header using ament_generate_version_header(..) (#1141)add RCL_RET_TIMEOUT to action service response. (#1138) * add RCL_RET_TIMEOUT to action service response. * address review comment. ———Update quality declaration documents (#1131)Remove most remaining uses of ament_target_dependencies. (#1102)Add~/get_type_descriptionservice (rep2011) (#1052)Modifies timers API to select autostart state (#1004)Contributors: Chris Lalancette, Christophe Bedard, Eloy Briceno, G.A. vd. Hoorn, Hans-Joachim Krauch, Tomoya Fujitarcl_interfacesUpdate the Log.msg constant types. (#161)Update the comments for SetParametersResult to reflect reality. (#159)Contributors: Chris Lalancettercl_lifecycleFixed warnings - strict-prototypes (#1148) (#1150)Generate version header using ament_generate_version_header(..) (#1141)Update quality declaration documents (#1131)Remove most remaining uses of ament_target_dependencies. (#1102)Use TRACETOOLS_ prefix for tracepoint-related macros (#1058)Contributors: Chris Lalancette, Christophe Bedard, G.A. vd. Hoorn, mergify[bot]rcl_logging_interfaceCheck allocator validity in some rcl_logging functions (#116) If the allocator is zero-initialized, it may cause a segfault when it is used later in the functions.Use (void) in declaration of param-less function (#114)add file_name_prefix parameter to external log configuration. (#109)Migrate to std::filesystem (#104)Remove the last uses of ament_target_dependencies in this repo. (#102)Contributors: Chris Lalancette, Christophe Bedard, Kenta Yonekura, Scott K Logan, Tomoya Fujitarcl_logging_noopadd file_name_prefix parameter to external log configuration. (#109)Remove the last uses of ament_target_dependencies in this repo. (#102)Contributors: Chris Lalancette, Tomoya Fujitarcl_logging_spdlogCheck allocator validity in some rcl_logging functions (#116) If the allocator is zero-initialized, it may cause a segfault when it is used later in the functions.Cleanup the tests. (#115) * Cleanup the tests. There are a few different fixes in here: 1. Move away from using “popen” to get the list of files in a directory. Instead, switch to using the C++ std::filesystem directory iterator and doing the work ourselves, which is portable and much less error-prone. 2. Set the ROS_LOG_DIR for all of the tests in here. This should make the test resistant to being run in parallel with other tests. 3. Consistently use rcpputils::set_env_var, rather than a mix of rcpputils and rcutils.Update quality declaration document (#112)Re-order rcl_logging_interface include (#111)add file_name_prefix parameter to external log configuration. (#109)Migrate to std::filesystem (#104)Remove the last uses of ament_target_dependencies in this repo. (#102)Contributors: Chris Lalancette, Christophe Bedard, Kenta Yonekura, Scott K Logan, Tomoya Fujitarcl_yaml_param_parserGenerate version header using ament_generate_version_header(..) (#1141)Update quality declaration documents (#1131)Fix for incorrect integer value conversion on Windows (#1126)Just remove rcpputils::fs dependency (#1105)Contributors: Christophe Bedard, G.A. vd. Hoorn, Kenta Yonekura, Michael Orlovrclcppadd impl pointer for ExecutorOptions (#2523) (#2525) * add impl pointer for ExecutorOptions (cherry picked from commit 343b29b617b163ad72b9fe3f6441dd4ed3d3af09) Co-authored-by: William Woodall Fixup Executor::spin_all() regression fix (#2517) (#2521) * test(Executors): Added tests for busy waiting Checks if executors are busy waiting while they should block in spin_some or spin_all. * fix: Reworked spinAll test This test was strange. It looked like, it assumed that spin_all did not return instantly. Also it was racy, as the thread could terminate instantly. * fix(Executor): Fixed spin_all not returning instantly is no work was available * Update rclcpp/test/rclcpp/executors/test_executors.cpp * test(executors): Added test for busy waiting while calling spin * fix(executor): Reset wait_result on every call to spin_some_impl Before, the method would not recollect available work in case of spin_some, spin_all. This would lead to the method behaving differently than to what the documentation states. * restore previous test logic for now * refactor spin_some_impl’s logic and improve busy wait tests * added some more comments about the implementation ——— Co-authored-by: Janosch Machowinski Co-authored-by: jmachowinski Co-authored-by: Tomoya Fujita Co-authored-by: William Woodall Revise the description of service configure_introspection() (#2511) (#2513)Remove references to index.ros.org. (#2504)Reduce overhead for inheriting from rclcpp::Executor when base functionality is not reused (#2506)[wjwwood] Updated “Data race fixes” (#2500) * Fix callback group logic in executor * fix: Fixed unnecessary copy of wait_set * fix(executor): Fixed race conditions with rebuild of wait_sets Before this change, the rebuild of wait set would be triggered after the wait set was waken up. With bad timing, this could lead to the rebuild not happening with multi threaded executor. * fix(Executor): Fixed lost of entities rebuild request * chore: Added assert for not set callback_group in execute_any_executable * Add test for cbg getting reset Co-authored-by: Janosch Machowinski * chore: renamed test cases to snake_case * style * fixup test to avoid polling and short timeouts * fix: Use correct notify_waitable_ instance * fix(StaticSingleThreadedExecutor): Added missing special case handling for current_notify_waitable_ * fix(TestCallbackGroup): Fixed test after change to timers ——— Co-authored-by: Janosch Machowinski Co-authored-by: Michael Carroll Co-authored-by: Janosch Machowinski fixup var names to snake case (#2501)Added optional TimerInfo to timer callback (#2343) Co-authored-by: Alexis Tsogias Co-authored-by: Janosch Machowinski Fix uninitialized memory in test (#2498) When I added in the tests for large messages, I made a mistake and reserved space in the strings, but didn’t actually expand it. Thus, we were writing into uninitialized memory. Fix this by just using the correct constructor for string, which will allocate and initialize the memory properly.Ensure waitables handle guard condition retriggering (#2483) Co-authored-by: Michael Carroll fix: init concatenated_vector with begin() & end() (#2492) * this commit will fix the warning [-Wstringop-overflow=]#2461Use the same context for the specified node in rclcpp::spin functions (#2433) * Use the same conext for the specified node in rclcpp::spin_xx functions * Add test for spinning with non-default-context * Format code ———Disable compare-function-pointers in test_utilities (#2489)address ambiguous auto variable. (#2481)Increase the cppcheck timeout to 1200 seconds (#2484)Removed test_timers_manager clang warning (#2479)Flaky timer test fix (#2469) * fix(time_source): Fixed possible race condition * fix(test_executors_time_cancel_behaviour): Fixed multiple race conditions ——— Co-authored-by: Janosch Machowinski Add tracepoint for generic publisher/subscriber (#2448)update rclcpp::Waitable API to use references and const (#2467)Utilize rclcpp::WaitSet as part of the executors (#2142) * Deprecate callback_group call taking context * Add base executor objects that can be used by implementors * Template common operations * Address reviewer feedback: * Add callback to EntitiesCollector constructor * Make function to check automatically added callback groups take a list * Lint * Address reviewer feedback and fix templates * Lint and docs * Make executor own the notify waitable * Add pending queue to collector, remove from waitable Also change node’s get_guard_condition to return shared_ptr * Change interrupt guard condition to shared_ptr Check if guard condition is valid before adding it to the waitable * Lint and docs * Utilize rclcpp::WaitSet as part of the executors * Don’t exchange atomic twice * Fix add_node and add more tests * Make get_notify_guard_condition follow API tick-tock * Improve callback group tick-tocking * Don’t lock twice * Address reviewer feedback * Add thread safety annotations and make locks consistent * @wip * Reset callback groups for multithreaded executor * Avoid many small function calls when building executables * Re-trigger guard condition if buffer has data * Address reviewer feedback * Trace points * Remove tracepoints * Reducing diff * Reduce diff * Uncrustify * Restore tests * Back to weak_ptr and reduce test time * reduce diff and lint * Restore static single threaded tests that weren’t working before * Restore more tests * Fix multithreaded test * Fix assert * Fix constructor test * Change ready_executables signature back * Don’t enforce removing callback groups before nodes * Remove the “add_valid_node” API * Only notify if the trigger condition is valid * Only trigger if valid and needed * Fix spin_some/spin_all implementation * Restore single threaded executor * Picking ABI-incompatible executor changes * Add PIMPL * Additional waitset prune * Fix bad merge * Expand test timeout * Introduce method to clear expired entities from a collection * Make sure to call remove_expired_entities(). * Prune queued work when callback group is removed * Prune subscriptions from dynamic storage * Styles fixes. * Re-trigger guard conditions * Condense to just use watiable.take_data * Lint * Address reviewer comments (nits) * Lock mutex when copying * Refactors to static single threaded based on reviewers * More small refactoring * Lint * Lint * Add ready executable accessors to WaitResult * Make use of accessors from wait_set * Fix tests * Fix more tests * Tidy up single threaded executor implementation * Don’t null out timer, rely on call * change how timers are checked from wait result in executors * peak -> peek * fix bug in next_waitable logic * fix bug in StaticSTE that broke the add callback groups to executor tests * style ——— Co-authored-by: Chris Lalancette Co-authored-by: William Woodall fix flakiness in TestTimersManager unit-test (#2468) the previous version of the test was relying on the assumption that a timer with 1ms period gets called at least 6 times if the main thread waits 15ms. this is true most of the times, but it’s not guaranteed, especially when running the test on windows CI servers. the new version of the test makes no assumptions on how much time it takes for the timers manager to invoke the timers, but rather focuses on ensuring that they are called the right amount of times, which is what’s important for the purpose of the testfix spin_some_max_duration unit-test for events-executor (#2465)refactor and improve the parameterized spin_some tests for executors (#2460) * refactor and improve the spin_some parameterized tests for executors * disable spin_some_max_duration for the StaticSingleThreadedExecutor and EventsExecutor * fixup and clarify the docstring for Executor::spin_some() * style * review comments ———enable simulation clock for timer canceling test. (#2458) * enable simulation clock for timer canceling test. * move MainExecutorTypes to test_executors_timer_cancel_behavior.cpp. ———Revert “relax the test simulation rate for timer canceling tests. (#2453)” (#2456) This reverts commit 1c350d0d7fb9c7158e0a39057112486ddbd38e9a.relax the test simulation rate for timer canceling tests. (#2453)Fix TypeAdapted publishing with large messages. (#2443) Mostly by ensuring we aren’t attempting to store large messages on the stack. Also add in tests. I verified that before these changes, the tests failed, while after them they succeed.Implement generic client (#2358) * Implement generic client * Fix the incorrect parameter declaration * Deleted copy constructor and assignment for FutureAndRequestId * Update codes after rebase * Address review comments * Address review comments from iuhilnehc-ynos * Correct an error in a description * Fix window build errors * Address review comments from William * Add doc strings to create_generic_client ———Rule of five: implement move operators (#2425)Various cleanups to deal with uncrustify 0.78. (#2439) These should also work with uncrustify 0.72.Remove the set_deprecated signatures in any_subscription_callback. (#2431) These have been deprecated since April 2021, so it is safe to remove them now.fix doxygen syntax for NodeInterfaces (#2428)Set hints to find the python version we actually want. (#2426) The comment in the commit explains the reasoning behind it.Update quality declaration documents (#2427)feat: add/minus for msg::Time and rclcpp::Duration (#2419) * feat: add/minus for msg::Time and rclcpp::DurationSplit test_executors up into smaller chunks. (#2421)[events executor] - Fix Behavior with Timer Cancel (#2375)Removed deprecated header (#2413)Make sure to mark RingBuffer methods as ‘override’. (#2410)Increase the cppcheck timeout to 600 seconds. (#2409)Add transient local durability support to publisher and subscriptions when using intra-process communication (#2303)Stop storing the context in the guard condition. (#2400)Updated GenericSubscription to AnySubscriptionCallback (#1928)make type support helper supported for service (#2209)Adding QoS to subscription options (#2323)Switch to target_link_libraries. (#2374)aligh with rcl that a rosout publisher of a node might not exist (#2357)Fix data race in EventHandlerBase (#2349)Support users holding onto shared pointers in the message memory pool (#2336)fix (signal_handler.hpp): spelling (#2356)Updates to not use std::move in some places. (#2353)rclcpp::Time::max() clock type support. (#2352)Serialized Messages with Topic Statistics (#2274)Add a custom deleter when constructing rcl_service_t (#2351)Disable the loaned messages inside the executor. (#2335)Use message_info in SubscriptionTopicStatistics instead of typed message (#2337)Add missing ‘enable_rosout’ comments (#2345)Adjust rclcpp usage of type description service (#2344)address rate related flaky tests. (#2329)Fixes pointed out by the clang analyzer. (#2339)Remove useless ROSRate class (#2326)add clients & services count (#2072)remove invalid sized allocation test for SerializedMessage. (#2330)Adding API to copy all parameters from one node to another (#2304)Add locking to protect the TimeSource::NodeState::node_base_ (#2320)Update SignalHandler get_global_signal_handler to avoid complex types in static memory (#2316)Removing Old Connext Tests (#2313)Documentation for list_parameters (#2315)Decouple rosout publisher init from node init. (#2174)fix the depth to relative in list_parameters (#2300)Fix the return type of Rate::period. (#2301)Update API docs links in package READMEs (#2302)Cleanup flaky timers_manager tests. (#2299)Topic correct typeadapter deduction (#2294)Fix C++20 allocator construct deprecation (#2292)Make Rate to select the clock to work with (#2123)Correct the position of a comment. (#2290)Remove unnecessary lambda captures in the tests. (#2289)Add rcl_logging_interface as an explicit dependency. (#2284)Revamp list_parameters to be more efficient and easier to read. (#2282)Do not crash Executor when send_response fails due to client failure. (#2276)Adding Custom Unknown Type Error (#2272)Add a pimpl inside rclcpp::Node for future distro backports (#2228)Remove an unused variable from the events executor tests. (#2270)Add spin_all shortcut (#2246)Adding Missing Group Exceptions (#2256)Change associated clocks storage to unordered_set (#2257)associated clocks should be protected by mutex. (#2255)Instrument loaned message publication code path (#2240)Implement get_node_type_descriptions_interface for lifecyclenode and add smoke test for it (#2237)Add new node interface TypeDescriptionsInterface to provide GetTypeDescription service (#2224)Move always_false_v to detail namespace (#2232)Revamp the test_subscription.cpp tests. (#2227)warning: comparison of integer expressions of different signedness (#2219)Modifies timers API to select autostart state (#2005)Enable callback group tests for connextdds (#2182)Fix up misspellings of “receive”. (#2208)Remove flaky stressAddRemoveNode test (#2206)Use TRACETOOLS_ prefix for tracepoint-related macros (#2162)remove nolint since ament_cpplint updated for the c++17 header (#2198)Feature/available capacity of ipm (#2173)add mutex to protect events_executor current entity collection (#2187)Declare rclcpp callbacks before the rcl entities (#2024)Fix race condition in events-executor (#2177)Add missing stdexcept include (#2186)Fix a format-security warning when building with clang (#2171)Fix delivered message kind (#2175)Contributors: AiVerisimilitude, Alberto Soragna, Alejandro Hernández Cordero, Alexey Merzlyakov, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Christopher Wecht, DensoADAS, Eloy Briceno, Emerson Knapp, Homalozoa X, HuaTsai, Jeffery Hsu, Jiaqi Li, Jonas Otto, Kotaro Yoshimoto, Lee, Luca Della Vedova, Lucas Wendland, Matt Condino, Michael Carroll, Michael Orlov, Minju, Nathan Wiebe Neufeldt, Steve Macenski, Tim Clephas, Tomoya Fujita, Tony Najjar, Tully Foote, William Woodall, Zard-C, h-suzuki-isp, jmachowinski, mauropasse, mergify[bot], methylDragon, Øystein Sturerclcpp_actionRemove references to index.ros.org. (#2504)Callback after cancel (#2281) * feat(Client): Added function to stop callbacks of a goal handle This function allows us to drop the handle in a locked context. If we do not do this within a lock, there will be a race condition between the deletion of the shared_ptr of the handle and the result / feedback callbacks. * fix: make Client goal handle recursive This fixes deadlocks due to release of goal handles in callbacks etc. * fix(ActionGoalClient): Fixed memory leak for nominal case This fixes a memory leak due to a self reference in the ClientGoalHandle. Note, this fix will only work, if the ClientGoalHandle ever receives a result callback. * doc: Updated documentation of rclcpp_action::Client::async_send_goal * docs: Made the async_send_goal documentation more explicit Co-authored-by: Janosch Machowinski Remake of “fix: Fixed race condition in action server between is_ready and take” (#2495) Some background information: is_ready, take_data and execute data may be called from different threads in any order. The code in the old state expected them to be called in series, without interruption. This lead to multiple race conditions, as the state of the pimpl objects was altered by the three functions in a non thread safe way. Co-authored-by: Janosch Machowinski update rclcpp::Waitable API to use references and const (#2467)Do not generate the exception when action service response timeout. (#2464) * Do not generate the exception when action service response timeout. * address review comment. ———Modify rclcpp_action::GoalUUID hashing algorithm (#2441) * Add unit tests for hashing rclcpp_action::GoalUUID’s * Use the FNV-1a hash algorithm for Goal UUIDVarious cleanups to deal with uncrustify 0.78. (#2439) These should also work with uncrustify 0.72.Update quality declaration documents (#2427)Switch to target_link_libraries. (#2374)Update API docs links in package READMEs (#2302)fix(ClientGoalHandle): Made mutex recursive to prevent deadlocks (#2267)Correct the position of a comment. (#2290)Fix a typo in a comment. (#2283)doc fix: callcanceledonly after goal state is in canceling. (#2266)Contributors: Chris Lalancette, Christophe Bedard, Jiaqi Li, Tomoya Fujita, William Woodall, jmachowinski, mauropasserclcpp_componentsRemove references to index.ros.org. (#2504)Add EXECUTOR docs (#2440)Update quality declaration documents (#2427)crash on no class found (#2415) * crash on no class found * error on no class found instead of no callback groups Co-authored-by: Chris Lalancette Switch to target_link_libraries. (#2374)feat(rclcpp_components): support events executor in node main template (#2366)fix(rclcpp_components): increase the service queue sizes in component_container (#2363)Add missing header required by the rclcpp::NodeOptions type (#2324)Update API docs links in package READMEs (#2302)Contributors: Adam Aposhian, Chris Lalancette, Christophe Bedard, Daisuke Nishimatsu, Ignacio Vizzo, M. Fatih Cırıt, Ruddick Lawrencerclcpp_lifecycleRevert “call shutdown in LifecycleNode dtor to avoid leaving the device in un… (#2450)” (#2522) (#2524) This reverts commit 04ea0bb00293387791522590b7347a2282cda290. (cherry picked from commit 42b0b5775b4e68718c5949308c9e1a059930ded7) Co-authored-by: Chris Lalancette Remove references to index.ros.org. (#2504)call shutdown in LifecycleNode dtor to avoid leaving the device in un… (#2450) * call shutdown in LifecycleNode dtor to avoid leaving the device in unknown state. * add test to verify LifecycleNode::shutdown is called on destructor. ———Update quality declaration documents (#2427)Increase timeout for rclcpp_lifecycle to 360 (#2395)Fix rclcpp_lifecycle inclusion on Windows. (#2331)add clients & services count (#2072)Update API docs links in package READMEs (#2302)add logger level service to lifecycle node. (#2277)Stop using constref signature of benchmark DoNotOptimize. (#2238)Implement get_node_type_descriptions_interface for lifecyclenode and add smoke test for it (#2237)Switch lifecycle to use the RCLCPP macros. (#2233)Add new node interface TypeDescriptionsInterface to provide GetTypeDescription service (#2224)Contributors: Chris Lalancette, Christophe Bedard, Emerson Knapp, Jorge Perez, Lee, Minju, Tomoya Fujita, mergify[bot]rclpyClock.py types. (#1244) * Start typing time.py * Testing out Enum wrapper for ClockType * convert to rcl_clock_type_t * Update create_time_point * add types to logging_service * Add types to duration.py * Add newlines for class definintions * update type alias name * Update to use Protocols * Add types to time.py * Add types * Fix import order * Started typing clock.py * Move typealias importpybind11 definition doc typo fixes. (#1270)Fix small flake8 error in rclpy. (#1267) Newer versions of flake8 complain that using ‘str’ as a variable shadows a builtin. Just make it ‘s’.Allow specifying qos (#1225)update RCL_RET_TIMEOUT error handling with action service response. (#1258)Add types to time_source.py (#1259)Small fixes for modern flake8. (#1264)Add types to qos_overriding_options.py (#1248)Add types to context.py (#1240)Add back Type hash __slots__ and add test cases. (#1245)Revert “Add types to TypeHash and moved away from __slots__ usage (#1232)” (#1243)Time.py Types (#1237)Add types to TypeHash and moved away from __slots__ usage (#1232)Add Static Typing to Validate files (#1230)Add types to duration.py (#1233)added python3-yaml (#1242)Add types to exceptions.py (#1241)Add types (#1231)Creates Enum wrapper for ClockType and ClockChange (#1235)Add types to expand_topic_name (#1238)Add types to logging_service.py (#1227)Add types to logging.py (#1226)forbid parameter to be declared statically without initialization. (#1216)Remove parentheses from assert statements. (#1213)Add doc-string warnings for destroy methods for services. (#1205)Add doc-string warnings for destroy() methods (#1204)Add an optional timeout_sec input to Client.call() to fix issuehttps://github.com/ros2/rclpy/issues/1181(#1188)aligh with rcl that a rosout publisher of a node might not exist (#1196)call ok() to see if rclpy and context is initialized. (#1198)Adjust python usage of the type_description service API (#1192)Document that spin_once() should not be called from multiple threads (#1079)making optional things Optional (#1182)Use timeout object to avoid callback losing in wait_for_ready_callbacks (#1165)Fix to issuehttps://github.com/ros2/rclpy/issues/1179(#1180)Add count services, clients & test (#1024)1105 parameter event handler (#1135)unregister_sigterm_signal_handler should be called. (#1170)Handle take failure in wait_for_message (#1172)Decouple rosout publisher init from node init. (#1121)Fix _list_parameters_callback & test (#1161)add list_parameters & test (#1124)Support to get remapped service name (#1156)a couple of typo fixes. (#1158)Fix get_type_description service bug and add a unit test (#1155)Fix an inherent race in execution vs. destruction. (#1150)Cleanup of test_node.py. (#1153)Avoid generating the exception when rcl_send_response times out. (#1136)Store time source clocks in a set (#1146)Fix spin_once_until_future_complete to quit when the future finishes. (#1143)get_type_description service (#1139)Add in the ability to start timers paused. (#1138)Modifies ros_timer_init for ros_timer_init2 (#999)Fix/param namespace association 894 (#1132)Include type hash in topic endpoint info (#1104)Fix iteration over modified list (#1129)making optional things Optional (#974)Fix type signature of Client.wait_for_service (#1128)Fix action server crash when the client goes away. (#1114)Turn Executor into a ContextManager (#1118)Turn Context into a ContextManager (#1117)Fix type in Node init args (#1115)Contributors: AndyZe, Anton Kesy, Barry Xu, Brian, Chen Lihui, Chris Lalancette, Eloy Briceno, Emerson Knapp, EsipovPA, Felix Divo, Hans-Joachim Krauch, KKSTB, Lee, Luca Della Vedova, M. Hofstätter, Michael Carlstrom, Michael Carroll, Minju, Russ, SnIcK, Steve Peters, Tim Clephas, Tomoya Fujita, mhidalgo-bdaircpputilsGenerate version header with ament_generate_version_header function (#190)Update docs for rcpputils::split functions (#188)Included tl_expected (#185)Switch to using target_link_libraries. (#183)Add a missing header due to missing PATH_MAX variable (#181)Add unique_lock implementation with clang thread safety annotations (#180)Add in a missing cstdint. (#178)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Christophe Bedard, Emerson Knapp, Sai Kishor Kothakota, wojciechmadryrcutilsRemoved warnings - strict-prototypes (#461) (#465)Increase timeout repl_str test (#463) (#464)validate the allocator before use. (#455) * validate the allocator before use. * address review comments. - validate allocator only if the function specifically uses. - argument null check comes before validation of value. ———feat: Add human readable date to logging formats (#441)Updates for uncrustify 0.78. (#454)Set hints to find the python version we actually want. (#451)Bring ament_add_gtest/target_link_libraries back together (#452)Change ‘ROS2’ to ‘ROS 2’ in quality declaration (#453)Allow parsing of escape sequence in log format (#443)Clean up unused references to mimick/mocking in tests (#450)Fix if(TARGET …) condition for test (#447)Zero-initialize rcutils_string_array_t in test_string_array (#446)Use rcutils_string_array_init in rcutils_split & handle alloc fail (#445)Make rcutils_split() return RCUTILS_RET_BAD_ALLOC if alloc fails (#444)Remove two last uses of ament_target_dependencies. (#440)time_win32: Update dead link (#438)memmove for overlaping memory (#434)make escape characters work (#426)Remove unused ‘max’ functions from sha256.c (#429)Contributors: Chen Lihui, Chris Lalancette, Christophe Bedard, Kaju-Bubanja, Marc Bestmann, Silvio Traversaro, Tomoya Fujita, Tyler Weaver, mergify[bot]resource_retrieverUpdate resource retreiver to use rule of five (#95)Use default ament_lint_auto (#92)Switch to target_link_libraries. (#89)Update to C++17 (#88)Contributors: Chris Lalancette, Michael CarrollrmwRemoved warnings - strict-prototypes (#365) (#366)Switch to target_link_libraries. (#361)Remove unnecessary c++14 flag. (#360)definition of local means being in the same context. (#359)typo fix. (#355)Contributors: Chris Lalancette, Tomoya Fujita, mergify[bot]rmw_connextddsAdd rmw count clients services impl (#93)Cleanup context implementation (#131)Update to C++17 (#125)Contributors: Chris Lalancette, Lee, Minjurmw_connextdds_commonRevert “Mitigate discovery race condition between clients and services (#132)” (#146) This reverts commit 7c95abbfc4559b293ebf5e94e20250bdd99d3ac6.Mitigate discovery race condition between clients and services (#132) * Mitigate discovery race condition between clients and services.Add: tracepoint for subscribe serialized_message (#145) * Add: tracepoint for take_serialized_message * Fix: TRACETOOLS_TRACEPOINT args * Update rmw_connextdds_common/src/common/rmw_subscription.cpp Co-authored-by: Christophe Bedard Support Fast CDR v2 (#141)Fix the rmw_connextdds_common build with gcc 13.2. (#142) The most important fix here is to #include , but also make sure we #include for all used STL functions.Fix basic request reply mapping for ConnextDDS Pro (#139)Add ros2_tracing tracepoints (#120)avoid using dds common public mutex directly (#134)Fix a couple of warnings pointed out by clang. (#133)Add rmw count clients services impl (#93)Conditional internal API access to support Connext 7+ (#121)Cleanup context implementation (#131)Fix RMW_Connext_Client::is_service_available for micro (#130)Update to C++17 (#125)Pass parameters in the correct order to DDS_DataReader_read in rmw_connextdds_count_unread_samples for micro (#129)Optimize QoS to improve responsiveness of reliable endpoints (#26)Clear out errors once we have handled them. (#126)Add support for listener callbacks (#76)Contributors: Andrea Sorbini, Chen Lihui, Chris Lalancette, Christopher Wecht, Lee, Miguel Company, Minju, h-suzuki-isprmw_connextddsmicroAdd rmw count clients services impl (#93)Cleanup context implementation (#131)Update to C++17 (#125)Contributors: Chris Lalancette, Lee, Minjurmw_cyclonedds_cppSet received_timestamp to system_clock::now() in message_info (#491) (#493) * Set received_timestamp to steady_clock::now() in message_info * Use ‘system_clock’ instead of ‘steady_clock’ * Also update receive_timestamp for services. (cherry picked from commit 76c9d8f38a03d160b258902af6d1d06f6ed9391e) Co-authored-by: Michael Orlov Add tracepoint for publish/subscribe serialized message (#485) Co-authored-by: eboasson Remove a bunch of unnecessary macros. (#482)compare string contents but string pointer addresses. (#481)Add timestamp to rmw_publish tracepoint (#454)avoid using dds common public mutex directly (#474)Add rmw count clients,services impl (#427)Minor revamp of the CMakeLists.txt. (#468)Clear out errors once we have handled them. (#464)Instrument loaned message publication code pathUse TRACETOOLS_ prefix for tracepoint-related macros (#450)Contributors: Chen Lihui, Chris Lalancette, Christophe Bedard, Christopher Wecht, Lee, Minju, Tomoya Fujita, h-suzuki-isp, mergify[bot]rmw_dds_commonAdd pkcs11 support to get_security_files (#66)make a new private mutex and add updating graph methods (#73)Just remove rcpputils::fs dependency (#72)Contributors: Chen Lihui, Kenta Yonekura, Miguel Companyrmw_fastrtps_cppSupport Fast CDR v2 (#746) * Require fastcdr version 2 * Changes to build rmw_fastrtps_shared_cpp * Changes to build rmw_fastrtps_cpp * Changes to build rmw_fastrtps_dynamic_cppCapturestd::bad_allocon deserializeROSmessage. (#665)Switch to target_link_libraries for linking. (#734)avoid using dds common public mutex directly (#725)Add rmw_count clients,services impl (#641)Improve node graph delivery by using a unique listening port (#711)Use TRACETOOLS_ prefix for tracepoint-related macros (#686)Contributors: Chen Lihui, Chris Lalancette, Christophe Bedard, Lee, Miguel Company, Minjurmw_fastrtps_dynamic_cppSupport Fast CDR v2 (#746) * Require fastcdr version 2 * Changes to build rmw_fastrtps_shared_cpp * Changes to build rmw_fastrtps_cpp * Changes to build rmw_fastrtps_dynamic_cppcompare string contents but string pointer addresses. (#744)Improve wide string (de)serialization in rwm_dynamic_fastrtps_cpp (#740) * Move type support headers to src * Fix references to moved headers * move macros.hpp to src/serialization_helpers.hpp * Move other non-api headers * Move common code into serialize_wide_string. * Move common code into deserialize_wide_string. * Move serialization into serialization_helpers.hpp * Move deserialization into serialization_helpers.hpp * Fix header guards * Linters * Do not account for extra character on serialized size calculation * Remove dependency on rosidl_typesupport_fastrtps_c(pp) ———Capturestd::bad_allocon deserializeROSmessage. (#665)Switch to target_link_libraries for linking. (#734)avoid using dds common public mutex directly (#725)Account for alignment on is_plain calculations. (#716)Add rmw_count clients,services impl (#641)Improve node graph delivery by using a unique listening port (#711)Contributors: Chen Lihui, Chris Lalancette, Lee, Miguel Company, Minju, Tomoya Fujitarmw_fastrtps_shared_cppAllow pkcs11 when calling rmw_dds_common::get_security_files. (#565) Co-authored-by: Miguel Company Add tracepoint for publish/subscribe serialized_message (#748) * Add: tracepoint for generic pub/sub * Fix: correspond to PR 454 * Fix: change write to write_to_timestamp ———Support Fast CDR v2 (#746) * Require fastcdr version 2 * Changes to build rmw_fastrtps_shared_cpp * Changes to build rmw_fastrtps_cpp * Changes to build rmw_fastrtps_dynamic_cppRemove an unnecessary constructor. (#743) We can just use brace initialization here, and this allows us to side-step an uncrustify issue with the constructor.Add timestamp to rmw_publish tracepoint (#694)Switch to Unix line endings. (#736)Switch to target_link_libraries for linking. (#734)Quiet compiler warning in Release mode. (#730)avoid using dds common public mutex directly (#725)Add rmw_count clients,services impl (#641)Switch to using rclcpp::unique_lock. (#712)Use DataWriter Qos to configure max_blocking_time on rmw_send_response (#704)Clear out errors once we have handled them. (#701)Instrument loaned message publication code path (#698)Add in a missing data_reader check when creating subscription. (#697)Use TRACETOOLS_ prefix for tracepoint-related macros (#686)typo fix. (#693)address clang nightly build error. (#689)Check for errors while doing an rmw_discovery_options_copy. (#690)Contributors: Chen Lihui, Chris Lalancette, Christophe Bedard, Christopher Wecht, IkerLuengo, Lee, Miguel Company, Minju, Tomoya Fujita, h-suzuki-isprmw_implementationUpdate quality declaration document (#225) (#226)Switch to using target_link_libraries everywhere. (#222)Add rmw_count_clients,services & test (#208)Contributors: Chris Lalancette, Lee, Minju, mergify[bot]robot_state_publisherFix reload after a description with a mimic joint (#212)Remove ament_target_dependencies. (#209)Improve log messages (#206)Contributors: Chris Lalancette, Guillaume Doisy, Nick Lamprianidisros2actioncall get_action_interfaces() properly. (#898) (#900) (cherry picked from commit 305ef763b83e42ebddc4802ac788869d178b6e93) Co-authored-by: Tomoya Fujita supportros2actiontype. (#894) * supportros2actiontype. * add review comments. ———Load a message/request/goal from standard input (#844)Contributors: Tomoya Fujita, mergify[bot], ymd-stellaros2bagAdd option to disable recorder keyboard controls (#1607)Support service 2/2 — rosbag2 service play (#1481)Added exclude-topic-types to record (#1582)Overhaul in the rosbag2_transport::TopicFilter class and relevant tests (#1585)Filter topic by type (#1577)Implement service recording and display info about recorded services (#1480)Add python3-yaml as a dependency (#1490)Fix the description of paramter ‘–topics’ for play (#1426)When using sim time, wait for /clock before beginning recording (#1378)Revert “Don’t record sim-time messages before first /clock (#1354)” (#1377)Don’t record sim-time messages before first /clock (#1354)Fix wrong descritpion for ‘–ignore-leaf-topics’ (#1344)Cleanup the help text for ros2 bag record. (#1329)Contributors: Alejandro Hernández Cordero, Barry Xu, Bernd Pfrommer, Chris Lalancette, Emerson Knapp, Michael Orlov, Michal Sojkaros2cliros2cli.node.daemon : try getting fdsize from /proc for open fd limit (#888)Fix the SIGTERM handling in the ros2 daemon. (#887)Replace unmaintainednetifaceslibrary to avoid local wheel builds (#875)make handles not inheritable to prevent from blocking durning tab-completion (#852)Add ros2 service info (#771)catch ExternalShutdownException ros2cli main. (#854)Load a message/request/goal from standard input (#844)Fix tests with get_type_description service and param present (#838)Add marshalling functions for rclpy.type_hash.TypeHash (rep2011) (#816)[service introspection] ros2 service echo (#745)Contributors: Brian, Chen Lihui, Chris Lalancette, Emerson Knapp, Hans-Joachim Krauch, Laurenz, Lee, Minju, Tomoya Fujita, akssri-sony, ymd-stellaros2cli_test_interfacesUpdate to C++17 (#848)Contributors: Chris Lalancetteros2componentWarning: get_parameter_value() is deprecated. (#866)Contributors: Tomoya Fujitaros2doctorRemove references tohttps://index.ros.org(#897)(ros2doctor) fix PackageCheck (#860) * (ros2doctor)(package) improve result string generationShutdown ros2doctor hello when ctrl-c is received (#826)Contributors: Chris Lalancette, Matthijs van der Burgh, Michael Carrollros2interfaceAdd interface type filters to ros2 interface package (#765)Contributors: David V. Lu!!ros2paramros2 param dump should handle empty list as exception. (#881)Warning: get_parameter_value() is deprecated. (#866)Fix tests with get_type_description service and param present (#838)Update ros2 param dump dosctring. (#837)Contributors: Emerson Knapp, Murilo M Marinho, Tomoya Fujitaros2pkgUpdate the package template for our new include directories. (#847)Fix typo in ros2pkg warning message. (#827)Contributors: Chris Lalancette, Tomoya Fujitaros2serviceAdd ros2 service info (#771)Load a message/request/goal from standard input (#844)Fix tests with get_type_description service and param present (#838)[service introspection] ros2 service echo (#745)Contributors: Brian, Emerson Knapp, Lee, Minju, ymd-stellaros2topicRemove parentheses from assert statement. (#878)Load a message/request/goal from standard input (#844)Add marshalling functions for rclpy.type_hash.TypeHash (rep2011) (#816)[service introspection] ros2 service echo (#745)Contributors: Brian, Chris Lalancette, Hans-Joachim Krauch, ymd-stellaros2traceReplace all occurences of index.ros.org (#114)Create start/pause/resume/stop sub-commands for ‘ros2 trace’ (#70)Switch to in pure Python packages (#67)Contributors: Chris Lalancette, Christophe Bedardrosbag2_compressionUse middleware send and receive timestamps from message_info during recording (#1531)Use std::filesystem instead of rcpputils::fs (#1576)Make some changes for newer versions of uncrustify. (#1578)Add topic_id returned by storage to the TopicMetadata (#1538)Add default initialization for CompressionOptions (#1539)Add option to set compression threads priority (#1457)Fixes pointed out by clang. (#1493)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)Add in a missing cstdint include. (#1321)Fix warning from ClassLoader in sequential compression reader and writer (#1299)Contributors: Arne B, Chris Lalancette, Michael Orlov, Patrick Roncagliolo, Roman Sokolkov, jmachowinskirosbag2_compression_zstdUse std::filesystem instead of rcpputils::fs (#1576)Make some changes for newer versions of uncrustify. (#1578)Contributors: Chris Lalancette, Roman Sokolkovrosbag2_cppSupport service 2/2 — rosbag2 service play (#1481)Use middleware send and receive timestamps from message_info during recording (#1531)Update to use yaml-cpp version 0.8.0. (#1605)Use std::filesystem instead of rcpputils::fs (#1576)Make some changes for newer versions of uncrustify. (#1578)Add topic_id returned by storage to the TopicMetadata (#1538)call cv.wait_until only if necessary. (#1521)Implement service recording and display info about recorded services (#1480)Switch to target_link_libraries everywhere. (#1504)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)ros2 bag convert now excludes messages not in [start_time;end_time] (#1455)Replace TSAUniqueLock implementation with rcpputils::unique_lock (#1454)Add BagSplitInfo service call on bag close (#1422)Rewrite TimeControllerClockTest.unpaused_sleep_returns_true to be correct (#1384)Implement storing and loading ROS_DISTRO from metadata.yaml and mcap files (#1241)Don’t crash when type definition cannot be found (#1350)Add recorder stop() API (#1300)Contributors: Barry Xu, Chris Lalancette, Emerson Knapp, Michael Orlov, Patrick Roncagliolo, Peter Favrholdt, Roman Sokolkov, Tomoya Fujita, jmachowinskirosbag2_examples_cppAdd topic_id returned by storage to the TopicMetadata (#1538)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)Contributors: Michael Orlov, Patrick Roncagliolorosbag2_examples_pyAdd topic_id returned by storage to the TopicMetadata (#1538)Fix a warning from python setuptools. (#1312)Contributors: Chris Lalancette, Michael Orlovrosbag2_interfacesAdd node name to the Read(Write)SplitEvent message (#1609)Contributors: Michael Orlovrosbag2_performance_benchmarkingUse middleware send and receive timestamps from message_info during recording (#1531)Update to use yaml-cpp version 0.8.0. (#1605)Add option to set compression threads priority (#1457)Add per group statistics for rosbag2_performance_benchmarking report (#1306)Set CPU affinity for producers and recorder from benchmark parameters (#1305)Add CPU usage to rosbag2_performance_benchmarking results report (#1304)Add config option to use storage_id parameter in benchmark_launch.py (#1303)Contributors: Chris Lalancette, Michael Orlov, jmachowinskirosbag2_pyAdd option to disable recorder keyboard controls (#1607)Support service 2/2 — rosbag2 service play (#1481)Use middleware send and receive timestamps from message_info during recording (#1531)Switch rclpy to be an exec_depend here. (#1606)Gracefully handle SIGINT and SIGTERM signals for play and burst CLI (#1557)Added exclude-topic-types to record (#1582)Fix for false negative tests in rosbag2_py (#1592)Update rosbag2_py stubs (#1593)Add Python stubs for rosbag2_py (#1459) (#1569)Filter topic by type (#1577)Add topic_id returned by storage to the TopicMetadata (#1538)Install signal handlers in recorder only inside record method (#1464)add missing import otherwise it doesnt compile (#1524)Implement service recording and display info about recorded services (#1480)Makerosbag2_transport::Player::play()run in a separate thread (#1503)Switch to target_link_libraries everywhere. (#1504)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)ros2 bag convert now excludes messages not in [start_time;end_time] (#1455)Add support for compression to python API (#1425)Gracefully handle SIGINT and SIGTERM in rosbag2 recorder (#1301)Implement storing and loading ROS_DISTRO from metadata.yaml and mcap files (#1241)Add binding to close the writer (#1339)Contributors: Alejandro Hernández Cordero, Andrew Symington, Barry Xu, Bernd Pfrommer, Chris Lalancette, Emerson Knapp, Michael Orlov, Mikael Arguedas, Patrick Roncagliolo, Peter Favrholdt, Roman Sokolkov, Yadu, jmachowinskirosbag2_storageSupport service 2/2 — rosbag2 service play (#1481)Use middleware send and receive timestamps from message_info during recording (#1531)Update to use yaml-cpp version 0.8.0. (#1605)Use std::filesystem instead of rcpputils::fs (#1576)Make some changes for newer versions of uncrustify. (#1578)Add topic_id returned by storage to the TopicMetadata (#1538)Remove rcpputils::fs dependencies from rosbag2_storages (#1558)Improve performance in SqliteStorage::get_bagfile_size() (#1516)Make Player and Recorder Composable (#902) (#1419)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)ros2 bag convert now excludes messages not in [start_time;end_time] (#1455)Fix missing cstdint include (#1383)Implement storing and loading ROS_DISTRO from metadata.yaml and mcap files (#1241)Contributors: Barry Xu, Chris Lalancette, Emerson Knapp, Michael Orlov, Patrick Roncagliolo, Peter Favrholdt, Roman Sokolkov, Zac Stanton, jmachowinskirosbag2_storage_mcapSupport service 2/2 — rosbag2 service play (#1481)Use middleware send and receive timestamps from message_info during recording (#1531)Update to use yaml-cpp version 0.8.0. (#1605)Check existence of a file before passing it to the mcap reader (#1594)Add topic_id returned by storage to the TopicMetadata (#1538)Use rw_lock to protect mcap metadata lists. (#1561)Remove rcpputils::fs dependencies from rosbag2_storages (#1558)remove unused headers (#1544)Link and compile against rosbag2_storage_mcap: Fixed issue 1492 (#1496)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)Store serialized metadata in MCAP file (#1423)Implement storing and loading ROS_DISTRO from metadata.yaml and mcap files (#1241)Contributors: Alejandro Hernández Cordero, Barry Xu, Chris Lalancette, Christopher Wecht, Emerson Knapp, Michael Orlov, Patrick Roncagliolo, Roman Sokolkov, Tomoya Fujita, jmachowinski, uupksrosbag2_storage_sqlite3Support service 2/2 — rosbag2 service play (#1481)Use middleware send and receive timestamps from message_info during recording (#1531)Update to use yaml-cpp version 0.8.0. (#1605)Make some changes for newer versions of uncrustify. (#1578)Add topic_id returned by storage to the TopicMetadata (#1538)Remove rcpputils::fs dependencies from rosbag2_storages (#1558)Change an incorrect TSA annotation. (#1552)Improve performance in SqliteStorage::get_bagfile_size() (#1516)Update rosbag2_storage_sqlite3 to C++17. (#1501)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)Stop inheriting from std::iterator. (#1424)Implement storing and loading ROS_DISTRO from metadata.yaml and mcap files (#1241)Store metadata in db3 file (#1294)Contributors: Barry Xu, Chris Lalancette, Emerson Knapp, Michael Orlov, Patrick Roncagliolo, Roman Sokolkov, jmachowinskirosbag2_test_commonSupport service 2/2 — rosbag2 service play (#1481)Make some changes for newer versions of uncrustify. (#1578)Implement service recording and display info about recorded services (#1480)Add extra checks in execute_and_wait_until_completion(..) (#1346)Address flakiness in rosbag2_play_end_to_end tests (#1297)Contributors: Barry Xu, Chris Lalancette, Michael Orlovrosbag2_test_msgdefsImplement service recording and display info about recorded services (#1480)Don’t crash when type definition cannot be found (#1350) * Don’t fail when type definition cannot be foundContributors: Barry Xu, Emerson Knapprosbag2_testsUse middleware send and receive timestamps from message_info during recording (#1531)Added exclude-topic-types to record (#1582)Use std::filesystem instead of rcpputils::fs (#1576)Filter topic by type (#1577)Make some changes for newer versions of uncrustify. (#1578)Add topic_id returned by storage to the TopicMetadata (#1538)Improve performance in SqliteStorage::get_bagfile_size() (#1516)Implement service recording and display info about recorded services (#1480)Mark play_end_to_end test as xfail in Windows (#1452)Implement storing and loading ROS_DISTRO from metadata.yaml and mcap files (#1241)Address flakiness in rosbag2_play_end_to_end tests (#1297)Contributors: Alejandro Hernández Cordero, Barry Xu, Chris Lalancette, Cristóbal Arroyo, Emerson Knapp, Michael Orlov, Roman Sokolkov, jmachowinskirosbag2_transportRemoved warnings - unqualified-std-cast-call (#1618) (#1622)Add node name to the Read(Write)SplitEvent message (#1609)Add option to disable recorder keyboard controls (#1607)Support service 2/2 — rosbag2 service play (#1481)Use middleware send and receive timestamps from message_info during recording (#1531)Update to use yaml-cpp version 0.8.0. (#1605)Gracefully handle SIGINT and SIGTERM signals for play and burst CLI (#1557)Added exclude-topic-types to record (#1582)Use std::filesystem instead of rcpputils::fs (#1576)Add transactional state mutex for RecorderImpl class. (#1547)Overhaul in the rosbag2_transport::TopicFilter class and relevant tests (#1585)Filter topic by type (#1577)fix: use size_t instead of uint64_t in play_options YAML converter (#1575)Make some changes for newer versions of uncrustify. (#1578)Add topic_id returned by storage to the TopicMetadata (#1538)Workaround for flaky test_play_services running with fastrtps (#1556)Add proper message for –start-paused (#1537)Recordingstoppedprints only once. (#1530)Cleanup the rosbag2_transport tests (#1518)Implement service recording and display info about recorded services (#1480)Add option to set compression threads priority (#1457)Bugfix for incorrect playback rate changes when pressing buttons (#1513)Make Player and Recorder Composable (#902) (#1419)Clang fixes for the latest PlayerImpl code. (#1507)Makerosbag2_transport::Player::play()run in a separate thread (#1503)Switch to target_link_libraries everywhere. (#1504)Use enum values for offered_qos_profiles in code and string names in serialized metadata (#1476)Redesign Player class with PIMPL idiom (#1447)Don’t warn for unknown types if topics are not selected (#1466)Remove unused concurrentqueue implementation. (#1465)Fix uninitialized value pointed out by clang static analysis. (#1440)Fix the build with rmw_fastrtps_dynamic. (#1416)Fix for rosbag2_transport::Recorder failures due to the unhandled exceptions (#1382)When using sim time, wait for /clock before beginning recording (#1378)Fix for possible freeze in Recorder::stop() (#1381)Revert “Don’t record sim-time messages before first /clock (#1354)” (#1377)Don’t record sim-time messages before first /clock (#1354)Fix a clang warning about uninitialized variable. (#1370)[bugfix] for parameters not passing to recorder’s node from child component (#1360)Change subscriptions from GenericSubscripton to SubscriptionBase (#1337)Add recorder stop() API (#1300)Contributors: Alejandro Hernández Cordero, Barry Xu, Bernd Pfrommer, Chris Lalancette, Christoph Fröhlich, Daisuke Nishimatsu, Emerson Knapp, Michael Orlov, Patrick Roncagliolo, Roman Sokolkov, Tomoya Fujita, jmachowinski, mergify[bot]rosidl_cmakeImprove deprecation notice of rosidl_target_interface to give a hint on how to update the code (#788)Add rosidl_find_package_idl helper function (#754)Remove unused splitting of .srv files in CMake (#753)Contributors: Alexis Paques, Mike Purvis, Shane Loretzrosidl_dynamic_typesupportuchar: fix conditional include/typedef (#10)uchar: use __has_include(..) on separate line (#8)Refactor the handling of nested types. (#7)Add C++ version check to char16 definition (#3)Contributors: Antonio Cuadros, Chris Lalancette, G.A. vd. Hoornrosidl_generator_cFixed warnings - strict-prototypes (#800) (#802)Set hints to find the python version we actually want. (#785)Add rosidl_find_package_idl helper function (#754)Fix IWYU for clangd in C and C++ (#742)Contributors: Alexis Paques, Chris Lalancette, Mike Purvis, mergify[bot]rosidl_generator_cppSet hints to find the python version we actually want. (#785)Fix constant generation for C++ floats (#772)Add rosidl_find_package_idl helper function (#754)Fixed visibility control file added to wrong header list variable. (#755)Fix deprecation warnings for message constants (#750)Generate typesupport declarations for actions, messages and services (#703)Fix IWYU for clangd in C and C++ (#742)Contributors: Alexis Paques, Chris Lalancette, Emerson Knapp, Mike Purvis, Stefan Fabianrosidl_generator_dds_idlRemove unnecessary parentheses. (#61)Contributors: Chris Lalancetterosidl_generator_pyRevert install of .so files into python path (#211) There seems that some regression might have happened after#195. When removing those 2 lines, we avoid to install the .so files in libandpython path.Prototype code for seeing if FindPython3 is usable for rosidl_python (#140)Add in a missing space. (#203)Install compiled libraries only to ‘lib’ (#195)Fix: Missing dependency that causes cmake error in downstream (resolveshttps://github.com/ros2/rosidl_python/issues/198) (#199)Contributors: Chris Lalancette, Isaac Saito, Matthias Schoepfer, Scott K Logan, Shane Loretzrosidl_generator_testsFixed warnings - strict-prototypes (#800) (#802)Increased the cpplint timeout to 300 seconds (#797)Fixes for modern uncrustify. (#793)Fix constant generation for C++ floats (#772)Fix same named types overriding typesources (#759)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Emerson Knapp, mergify[bot]rosidl_generator_type_descriptionSet hints to find the python version we actually want. (#785)Remove unnecessary parentheses. (#783)Contributors: Chris Lalancetterosidl_parserAdding interfaces to support@keyannotation (#796) Co-authored-by: Mario Dominguez Small fix for newer flake8 compatibility. (#792)Remove unnecessary parentheses. (#783)Contributors: Chris Lalancette, Miguel Companyrosidl_pycommonRemove unnecessary parentheses. (#783)Fix same named types overriding typesources (#759)Contributors: Chris Lalancette, Emerson Knapprosidl_runtime_cSwitch to target_link_libraries. (#776)Set the C++ version to 17. (#761)Mark _ in benchmark tests as unused. (#741) This helps clang static analysis.Contributors: Chris Lalancetterosidl_runtime_cppSuppress a warning around BoundedVector. (#803) (#804) The comment has more explanation, but in short GCC 13 has false positives around some warnings, so we suppress it for BoundedVector. (cherry picked from commit 858e76adb03edba00469b91d50dd5fe0dcb34236) Co-authored-by: Chris Lalancette Contributors: mergify[bot]rosidl_runtime_pySome fixes for modern flake8. (#25)Contributors: Chris Lalancetterosidl_typesupport_cFixed warnings - strict-prototypes (#155) (#156)compare string contents but string pointer addresses. (#153)Set hints to find the python version we actually want. (#150)Don’t override user provided compile definitions (#145)Contributors: Chris Lalancette, Emerson Knapp, Tomoya Fujita, mergify[bot]rosidl_typesupport_cppcompare string contents but string pointer addresses. (#153)Set hints to find the python version we actually want. (#150)Don’t override user provided compile definitions (#145)Added C interfaces to obtain service and action type support. (#143)Contributors: Chris Lalancette, Emerson Knapp, Stefan Fabian, Tomoya Fujitarosidl_typesupport_fastrtps_cAdding interfaces to support@keyannotation (#116) Co-authored-by: Mario Dominguez Support Fast CDR v2 (#114)Improve wide string (de)serialization (#113)Set hints to find the python version we actually want. (#112) Co-authored-by: Michael Carroll Update to C++17 (#111)Account for alignment onis_plaincalculations (#108)Contributors: Chris Lalancette, Miguel Companyrosidl_typesupport_fastrtps_cppFix how header template works to prevent double-inclusion (#117) Co-authored-by: Alejandro Hernández Cordero Adding interfaces to support@keyannotation (#116) Co-authored-by: Mario Dominguez Support Fast CDR v2 (#114)Improve wide string (de)serialization (#113)Set hints to find the python version we actually want. (#112) Co-authored-by: Michael Carroll Update to C++17 (#111)Account for alignment onis_plaincalculations (#108)Avoid redundant declarations in generated code for services and actions (#102)Contributors: Chris Lalancette, Emerson Knapp, Michael Carroll, Miguel Companyrosidl_typesupport_introspection_cFixed warnings - strict-prototypes (#800) (#802)Adding interfaces to support@keyannotation (#796) Co-authored-by: Mario Dominguez Set hints to find the python version we actually want. (#785)Add rosidl_find_package_idl helper function (#754)update comment (#757)Contributors: Chen Lihui, Chris Lalancette, Miguel Company, Mike Purvis, mergify[bot]rosidl_typesupport_introspection_cppAdding interfaces to support@keyannotation (#796) Co-authored-by: Mario Dominguez Set hints to find the python version we actually want. (#785)Switch to target_link_libraries. (#776)Add rosidl_find_package_idl helper function (#754)update comment (#757)Fix deprecation warnings for message constants (#750)Contributors: Chen Lihui, Chris Lalancette, Emerson Knapp, Miguel Company, Mike Purvisrosidl_typesupport_introspection_testsOne last uncrustify fix for newer uncrustify. (#795)Disable zero-variadic-macro-arguments warning when using clang. (#768)Fixed C++20 warning implicit capture of this in lambda (#766)Contributors: AiVerisimilitude, Chris Lalancetterosidl_typesupport_testsSuppress uncrustify on long lines. (#152)Contributors: Chris Lalancetterpyutilscorrect the URL and f-strings format (#11)Contributors: Chen LihuirqtAdd a test dependency on pytest. (#306)Contributors: Chris Lalancetterqt_bagAdd in copyright tests to rqt_bag. (#154)Add a test dependency on pytest. (#153)Revert “Add a dependency on pytest to rqt_bag and rqt_bag_plugins. (#… (#151)Update maintainer to myself. (#150)Update maintainer list in package.xml files (#149)Add a dependency on pytest to rqt_bag and rqt_bag_plugins. (#148)[ros2] Enable Save (#142)Call close (#141)Use default storage id (#139)Contributors: Chris Lalancette, Michael Jeronimo, Yadu, Yadunundrqt_bag_pluginsAdd a test dependency on pytest. (#153)Revert “Add a dependency on pytest to rqt_bag and rqt_bag_plugins. (#… (#151)Update maintainer to myself. (#150)Update maintainer list in package.xml files (#149)Add a dependency on pytest to rqt_bag and rqt_bag_plugins. (#148)Contributors: Chris Lalancette, Michael Jeronimorqt_consoleAdd a test dependency on pytest. (#45)Contributors: Arne Hitzmann, Chris Lalancetterqt_graphUpdate maintainer list in package.xml files (#92)Add a test dependency on python3-pytest. (#91)Refresh rosgraph when params checkbox is clicked (#86)Contributors: Chris Lalancette, Michael Jeronimo, Yadunundrqt_gui_cppSwitch to target_link_libraries. (#297)Contributors: Chris Lalancetterqt_gui_pyfix an exception raised while press ctrl+c to exit (#291)Contributors: Chen Lihuirqt_msgAdd in python3-pytest test dependency. (#19)Small cleanups to rqt_msg (#16)Contributors: Chris Lalancetterqt_plotAdd in copyright tests to rqt_bag. (#95)Add a test dependency on pytest. (#94)Add in a pytest dependency for running tests. (#92)Fix regression from #87 (#90)Contributors: Chris Lalancette, Yadunundrqt_publisherUse raw strings for regular expressions. (#44)Switch maintainer to me. (#43)Update maintainer list in package.xml files (#42)Add in a test dependency on pytest. (#41)Contributors: Chris Lalancette, Michael Jeronimorqt_py_commonAllow to autocomplete namespaced topics (#299)Contributors: Alejandro Hernández Corderorqt_py_consoleAdd in test dependency on pytest. (#16)Fix a crash in the rqt_py_console dialog box. (#15)Contributors: Chris Lalancetterqt_reconfigureExplicitly add a pytest test dependency. (#141)Remove unnecessary parentheses around if statements. (#140)Fixed executor conflict (#126)Add param filtering (#128)Fix handling of namespaces in the node tree (#132)Contributors: Aleksander Szymański, Chris Lalancette, Devarsi Rawal, Nick Lamprianidisrqt_service_callerAdd in a pytest test dependency. (#28)Contributors: Chris Lalancetterqt_shellChange maintainer to clalancette. (#21)Add in pytest test dependency. (#19)Contributors: Chris Lalancette, Michael Jeronimorqt_srvAdd explicit dependency to python3-pytest. (#12)Minor cleanups in rqt_srv for ROS 2 (#9)Contributors: Chris Lalancetterqt_topicSmall fix for modern flake8. (#50)Add explicit python3-pytest dependency. (#48)Contributors: Chris Lalancetterti_connext_dds_cmake_moduleUse unified approach for checking the existence of environment variables (#105)Contributors: Christopher WechtrttestUpdate to C++17 (#124)Contributors: Chris Lalancetterviz2Add “R” key as shortcut for resetTime (#1088)Switch to target_link_libraries. (#1098)Contributors: Chris Lalancette, Paul Erik Frivoldrviz_assimp_vendorRemoved assimp warnings (#1191) (#1192) (cherry picked from commit e8dd485d19a35d3abba905020741973e613334e3) Co-authored-by: Alejandro Hernández Cordero Update the vendored package path. (#1184) Since we just updated to assimp 5.3, we also need to update the path we look for it. This should fix the build with clang which is currently failing.Update assimp vendor to 5.3.1 (#1182) This matches what is in Ubuntu 24.04.Update to assimp 5.2.2 (#968)Fix the vendoring flags for clang compilation. (#1003)Switch to ament_cmake_vendor_package (#995)Contributors: Chris Lalancette, Scott K Logan, mergify[bot]rviz_commonUpdate to yaml-cpp 0.8.0 (#1183) yaml-cpp 0.8.0 has a proper CMake target, i.e. yaml-cpp::yaml-cpp. Use that here.Remove regex_filter_property.hpp from the moc lines. (#1172) Since it has no SLOTS or SIGNALS, we don’t need to run MOC on it. That will both speed up the compilation and remove a warning when building.Added regex filter field for TF display (#1032)Fix camera display overlay (#1151)Fixes for uncrustify 0.78. (#1155) Mostly what we do here is to disable the indentation on certain constructs that are different between 0.72 and 0.78. It isn’t my preferred solution, but since it only affects a small amount of code (and most of that in macros), this seems acceptable to me.Append measured subscription frequency to topic status (#1113)Implement reset time service (#1109)Add “R” key as shortcut for resetTime (#1088)Add fullscreen startup option (#1097)Switch to target_link_libraries. (#1098)Initialize more of the visualization_manager members. (#1090)Explicit time conversions and comparisons (#1087)Rolling namespace in title (#1074)Removed unused code (#1044)Remove unused LineEditWithButton::simulateReturnPressed() (#1040)Remove warning in depth_cloud_mld.cpp (#1021)Added DepthCloud default plugin (#996)Stop inheriting from std::iterator. (#1013) In C++17, inheriting from std::iterator has been deprecated: https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/ Here, switch away from inheriting and just define the interface ourselves (which is the current recommended best practice). This removes some warnings when building with gcc 13.1.1use static QCoreApplication::processEvents() function without a QApplication instance (#924)Re-implemented setName for tools (#989)Add a libqt5-svg dependency to rviz_common. (#992)Remove onHelpWiki. (#985)Clean Code (#975)Contributors: AiVerisimilitude, Alejandro Hernández Cordero, Chris Lalancette, Felix Exner (fexner), Hyunseok, Markus Bader, Paul Erik Frivold, Yadu, Yannis Gerlach, mosfet80rviz_default_pluginsMake sure to export all rviz_default_plugins dependencies. (#1181)Increase the cpplint timeout to 180 seconds. (#1179)Switch to gz_math_vendor. (#1177)Fixed camera info warning (#1175)Added CameraInfo display (#1166)apply origin rotation to inertia box visualization (#1171)Added regex filter field for TF display (#1032)Added point_cloud_transport (#1008)Select QoS reliability policy in DepthCloud Plugin (#1159)Fixed crash on DepthCloud plugin (#1161)Fixes for uncrustify 0.78. (#1155) Mostly what we do here is to disable the indentation on certain constructs that are different between 0.72 and 0.78. It isn’t my preferred solution, but since it only affects a small amount of code (and most of that in macros), this seems acceptable to me.Fixed crash on DepthCloudPlugin (#1133)Wrench accepth nan values fix (#1141)DepthCloud plugin: Append measured subscription frequency to topic status (#1137)Added Cache to camera display for TimeExact (#1138)Fixed transport name in DepthCloud plugin (#1134)Fix time-syncing message (#1121)Switch from ROS_TIME to SYSTEM_TIME on rclcpp::Time construction (#1117)Append measured subscription frequency to topic status (#1113)Fix typo (#1104)Fix potencial leak / seg fault (#726)Fixed screw display (#1093)Explicit time conversions and comparisons (#1087)Handle missing effort limit in URDF (#1084)(robot) fix styling of log msg (#1080)Fix image display wrapping (#1038)removed enableInteraction reference (#1075)Fix ODR violations in interactive_marker displays. (#1068)Improve error handling in LaserScanDisplay (#1035)Fix implicit capture of “this” warning in C++20 (#1053)Removed unused code (#1044)Fixed AccelStamped, TwistStamped and Wrench icons (#1041)Fix the flakey rviz_rendering tests (#1026)Don’t pass screw_display.hpp to the moc generator. (#1018) Since it isn’t a Qt class, you get a warning from moc: Note: No relevant classes found. No output generated. Just skip adding it to the moc list here, which gets rid of the warning.Added DepthCloud default plugin (#996)Added TwistStamped and AccelStamped default plugins (#991)Added Effort plugin (#990)Improve the compilation time of rviz_default_plugins (#1007)Switch to ament_cmake_vendor_package (#995)Modify access specifier to protected or public for the scope of processMessage() member function (#984)Contributors: AiVerisimilitude, Alejandro Hernández Cordero, Austin Moore, Chris Lalancette, Christoph Fröhlich, Hyunseok, Jonas Otto, Lewe Christiansen, Matthijs van der Burgh, Patrick Roncagliolo, Scott K Logan, Yadurviz_ogre_vendorUpdate zlib into CMakeLists.txt (#1128) (#1195) Changes in 1.3 (18 Aug 2023) - Remove K&R function definitions and zlib2ansi - Fix bug in deflateBound() for level 0 and memLevel 9 - Fix bug when gzungetc() is used immediately after gzopen() - Fix bug when using gzflush() with a very small buffer - Fix crash when gzsetparams() attempted for transparent write - Fix test/example.c to work with FORCE_STORED - Rewrite of zran in examples (see zran.c version history) - Fix minizip to allow it to open an empty zip file - Fix reading disk number start on zip64 files in minizip - Fix logic error in minizip argument processing - Add minizip testing to Makefile - Read multiple bytes instead of byte-by-byte in minizip unzip.c - Add memory sanitizer to configure (–memory) - Various portability improvements - Various documentation improvements - Various spelling and typo corrections Co-authored-by: Chris Lalancette (cherry picked from commit 32eb8b9404927883247e868ab0c7d62b80df2ed1) Co-authored-by: mosfet80 Change an rviz_ogre_vendor dependency to libfreetype-dev. (#1167) The situation is complicated, but in versions of Ubuntu prior to Focal and versions of Debian prior to Bookworm, the name of the library was ‘libfreetype6-dev’. Since Focal and Bookworm, the name of the library is ‘libfreetype-dev’. While ‘libfreetype-dev’ provides a “virtual package” for ‘libfreetype6-dev’, we should really use the new canonical name. Further, there is currently a bug on ros_buildfarm where it doesn’t properly deal with “virtual packages” like this. This is currently preventing this package from building on Ubuntu Noble. That bug is being worked on separately. Finally, I’ll note that we already have a libfreetype-dev key in rosdep, so we just switch to using that here which should work around the bug on the buildfarm, and also use the correct canonical name going forward.fix: modify typo in cmake args for mac (#1160)feat: support macos (#1156)Suppress a couple more of clang warnings in rviz_ogre_vendor. (#1102)Fix the vendoring flags for clang compilation. (#1003) Several of the flags are not available on clang, so don’t add them there. This fixes the clang build for me locally.Switch to ament_cmake_vendor_package (#995)CMake: rename FeatureSummary.cmake to avoid name clashes (#953)FIX CVE in external libraries (#961)Contributors: Chris Lalancette, Daisuke Nishimatsu, Gökçe Aydos, Scott K Logan, mergify[bot], mosfet80rviz_renderingAdded CameraInfo display (#1166)Fix camera display overlay (#1151)Fixes for uncrustify 0.78. (#1155) Mostly what we do here is to disable the indentation on certain constructs that are different between 0.72 and 0.78. It isn’t my preferred solution, but since it only affects a small amount of code (and most of that in macros), this seems acceptable to me.fixed MovableText::getWorldTransforms transform (#1118)Switch to target_link_libraries. (#1098)Update rviz_rendering and rviz_rendering_tests to C++17. (#1096)Include MeshShape class (#1064)Use assimp to load stl (#1063)RVIZ_RENDERING_PUBLIC to export class RenderSystem (#1072)Restore the maybe-uninitialized flag in covariance_visual.hpp (#1071)Fix up warnings when building with clang. (#1070)Use buildsystem info to get the ros_package_name (#1062)make box-mode point cloud shader lighter on top than bottom (#1058)Removed warning when building in release mode (#1057)Fixed low FPS when sending point markers (#1049)Removed unused code (#1044)Fix the flakey rviz_rendering tests (#1026)Added TwistStamped and AccelStamped default plugins (#991)Added Effort plugin (#990)load GLB meshes (#1001)Fixed camera default plusin crash (#999)Clean Code (#975) * Clean CodeContributors: Alejandro Hernández Cordero, Chris Lalancette, Felix F Xu, Morgan Quigley, Yaswanth, mosfet80rviz_rendering_testsRemove the loading_ascii_stl_files_fail (#1125)Update rviz_rendering and rviz_rendering_tests to C++17. (#1096)Use assimp to load stl (#1063)Contributors: Alejandro Hernández Cordero, Chris Lalancetterviz_visual_testing_frameworkImprove the compilation time of rviz_default_plugins (#1007)Contributors: Chris Lalancettesensor_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).[J-Turtle] Fix uninitialized values in NavSatFix and add missing NavSatStatus UNKNOWN (#220) * Fix unitialized values in NavSatFix and add missing UNKNOWN * Fixes#196* Fix default initialization instead of constants * Define SERVICE_UNKNOWN Co-authored-by: Tully Foote Co-authored-by: Martin Pecka Use target qualifier for checking the cpp typesupport exists (#238)sensor_msgs/CompressedImage: updated description of format field (#231)Return true for isColor if format is YUYV or UYUV (#229)Contributors: Chris Lalancette, Kenji Brameld, Ryansensor_msgs_pyClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Allow pointcloud create_cloud function to set specific point_step (#223)Fix read_points_numpy field_names parameterContributors: Chris Lalancette, George Broughtonshape_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancetteshared_queues_vendorRemove unused concurrentqueue implementation. (#1465) rosbag2 only depends on the readerwriter queue.Contributors: Chris Lalancettespdlog_vendorRemoved spdlog_vendor warnings (#36) (#37) (cherry picked from commit 4510d9ab4389f84daac77210f3fdf8aab372b938) Co-authored-by: Alejandro Hernández Cordero Upgrade to v1.12.0. (#35)Switch to ament_cmake_vendor_package (#34)Contributors: Marco A. Gutierrez, Scott K Logan, mergify[bot]sqlite3_vendorSwitch to ament_cmake_vendor_package (#1400)Contributors: Scott K Logansros2Fix linux tutorial: cloning example policies and set of default policies for a node (#295) (#296) * clone policies to temporary dir as subversion hack doesnt work anymore * add get_type_description service to policies * update MacOS similarly * update all permissions with new topics * dont rule out cycloneDDS * example of enclave override Co-authored-by: Chris Lalancette (cherry picked from commit ca6bb12cc650b73e7ccfc0fa789d8b49358d44ad) Co-authored-by: Mikael Arguedas Use modern PKCS7 to sign the certificate bytes. (#290)Fix a number of warnings on Ubuntu 24.04. (#289)Fix SSH commands in SROS2_Linux.md (#286)Contributors: Boris Boutillier, Chris Lalancette, mergify[bot]std_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancettestd_srvsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancettestereo_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancettetest_cliSwitch to target_link_libraries everywhere. (#532)Contributors: Chris Lalancettetest_cli_remappingSwitch to target_link_libraries everywhere. (#532)Contributors: Chris Lalancettetest_communicationSmall fix for modern flake8. (#539)Switch to target_link_libraries everywhere. (#532)Add integration test for nested messages. (#530)Adjust for new rclcpp::Rate API (#516)Contributors: Alexey Merzlyakov, Chris Lalancettetest_launch_rosSmall fixes for modern flake8. (#395)add “–log-file-name” command line argument for test. (#387)Fix an assert in the test_launch_ros tests. (#367)Fix misspelled “receive”. (#362)Contributors: Chris Lalancette, Tomoya Fujitatest_launch_testingUpdate to C++17 (#742)Contributors: Chris Lalancettetest_msgsIncrease the timeout for the test_msgs rosidl_generated_cpp cpplint. (#163) This should make it much more likely to succeed on Windows.Fix for invalid conversion from const char8_t* to char for C++20 (#160)Contributors: AiVerisimilitude, Chris Lalancettetest_quality_of_serviceCleanup header includes in test_quality_of_service. (#533)Switch to target_link_libraries everywhere. (#532)Fix test QoS on macOS by moving qos_utilities.cpp to the four tests; fixes#517(#518)Contributors: Chris Lalancette, PhDittmanntest_rclcppAddressed TODO in test_local_parameters (#545)Actually skip the gtest_subscription test on Connext. (#544)Increased time in test_multithreaded (#543)Improve the node_name test. (#538)Change up the formatting in the test_rclcpp tests. (#537)Revamp test_rclcpp to compile far few files. (#535)Mark gtest_subscription__rmw_connextdds xfail. (#531)refactor corrected depth check for prefix in parameter_fixtures.hpp (#529)Remove an unnecessary capture in test_rclcpp. (#527)Cleanup of the CMakeLists.txt for test_rclcpp. (#526)Add a fix for the tests given the new type description parameter (#520)Changes ros_timer_init for ros_timer_init2 (#508)refactor the multi_access_publisher test to avoid dead locks (#515)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Eloy Briceno, Emerson Knapp, Lee, Minju, William Woodalltest_rmw_implementationCompile the test_rmw_implementation tests fewer times. (#224)Switch to using target_link_libraries everywhere. (#222)Add rmw_count_clients,services & test (#208)Contributors: Chris Lalancette, Lee, Minjutest_ros2traceAdd explicit context fields test to test_ros2trace (#107)Allow tracing tests to be run in parallel with other tests (#95)Make test_ros2trace depend on test_tracetools_launch.Switch to custom lttng-ctl Python bindings (#81)Contributors: Chris Lalancette, Christophe Bedardtest_securityUpdate to C++17 (#528)Switch to target_link_libraries everywhere. (#532)Adjust for new rclcpp::Rate API (#516)Extract sros_artifacts fixture into a CMake script (#525)Use test fixtures to create SROS artifacts (#522)Contributors: Alexey Merzlyakov, Chris Lalancette, Scott K Logantest_tf2Compile fix for upcomming changes to rclcpp::Executor (#668)Adding addition BUILD_TESTING requirement (#660)normalize quaternions on tf2_eigen (#644)Contributors: Lucas Wendland, Paul Gesel, jmachowinskitest_tracetoolsImprove tracetools_test and simplify test_tracetools code (#109)Install test_tracetools_mark_process (#113)Remove unnecessary include (#111)Include in mark_process.cpp (#110)Remove unnecessary print in test (#108)Add test for GenericPublisher/Subscriber (#97)Use lttng_ust_tracef instead of lttng_ust__tracef (#103)Use a memcmp for the expected symbol name. (#100)Fix the build on RHEL-9. (#98)Allow tracing tests to be run in parallel with other tests (#95)Fix interference between test_tracetools and ros2lifecycle tests (#96)Make tracing test assert messages more descriptive (#93)Update tests and docs after new rmw_publish timestamp field (#90)Switch to target_link_libraries in test_tracetools. (#83)Improve test coverage of rclcpp_callback_register in test_tracetools (#69)Disable tracing on Android (#71)Contributors: Chris Lalancette, Christophe Bedard, Przemysław Dąbrowski, h-suzuki-isptest_tracetools_launchImprove tracing configuration error reporting (#85)Contributors: Christophe Bedardtf2Enable Twist interpolator (#646) Co-authored-by: Tully Foote Warning Message Intervals for canTransform (#663)Nacho/minor fixes tf2 cache (#658)Removing console_bridge (#655)Fix constantly increasing memory in std::list (#636)Update the tf2 documentation (#638)Fix error code returned in BufferCore::walkToTopParent (#601)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Ignacio Vizzo, Lucas Wendland, Patrick Roncagliolotf2_bulletRemoved obsolete headers (#645)Contributors: Alejandro Hernández Corderotf2_eigenRemoved obsolete headers (#645)normalize quaternions on tf2_eigen (#644)Fix clang build warnings. (#628)Add another reference for twist transformation. Comment correction. (#620)Contributors: Alejandro Hernández Cordero, AndyZe, Chris Lalancette, Paul Geseltf2_eigen_kdlFix installation directory of .dll files in tf2_eigen_kdl (#657)Remove unnecessary use of ament_target_dependencies. (#637) We can just use target_link_libraries instead.Fix clang build warnings. (#628)Contributors: Chris Lalancette, Silvio Traversarotf2_geometry_msgsEnable Twist interpolator (#646) Co-authored-by: Tully Foote Removed obsolete headers (#645)Add doTransform support for Point32, Polygon and PolygonStamped (backport#616) (#619)Contributors: Alejandro Hernández Cordero, mergify[bot]tf2_kdlRemoved obsolete headers (#645)Contributors: Alejandro Hernández Corderotf2_pyEnable Twist interpolator (#646) Co-authored-by: Tully Foote Contributors: Alejandro Hernández Corderotf2_rosCompile fix for upcomming changes to rclcpp::Executor (#668)Enable Twist interpolator (#646) Co-authored-by: Tully Foote Adding NodeInterfaces to Buffer (#656)Reformat some code to make uncrustify happier. (#654)Enable intra-process (#649) (#642)Avoid unecessary time conversions. (#635)Expose TF2 listener CB (#632)Fix invalid timer handle exception (#474)Fix for#589- Should be able to transform with default timeout (#593)Enable StaticTransformBroadcaster in Intra-process enabled components (#607)Contributors: AiVerisimilitude, Alejandro Hernández Cordero, Chris Lalancette, Cliff Wu, Lucas Wendland, Patrick Roncagliolo, Steve Macenski, jmachowinski, vineet131tf2_ros_pyTransform Data Callback Python (#664)Make sure to cache transforms in tf2_ros_py. (#634)Remove ‘efficient copy’ prints (#625)Add time jump callback (#608)Contributors: Chris Lalancette, Erich L Foster, Lucas Wendland, Matthijs van der Burghtf2_sensor_msgsRemoved obsolete headers (#645)Fix clang build warnings. (#628)Contributors: Alejandro Hernández Cordero, Chris Lalancettetf2_tools[view_frames] log filenames after it’s been determined (#674) (#675) (cherry picked from commit 24643fce510d8cc836fe6e5277a1d3f86a21af04) Co-authored-by: Mikael Arguedas Add in tests for tf2_tools. (#647)Contributors: Chris Lalancette, mergify[bot]topic_monitorUpdate maintainer list in package.xml files (#665)fix readme for topic_monitor. (#630)Contributors: Michael Jeronimo, Tomoya Fujitatopic_statistics_demoUpdate maintainer list in package.xml files (#665)Contributors: Michael JeronimotracetoolsReplace all occurences of index.ros.org (#114)Switch to ament_generate_version_header for tracetools (#112)Fixes for newer uncrustify (#101)Update tests and docs after new rmw_publish timestamp field (#90)Add timestamp to rmw_publish tracepoint (#74)Add TRACETOOLS_ prefix to tracepoint-related public macros (#56)Disable tracing on Android (#71)Add new rclcpp_subscription_init tracepoint to support new intra-process commsContributors: Chris Lalancette, Christophe Bedard, Christopher Wecht, Przemysław Dąbrowskitracetools_launchReplace all occurences of index.ros.org (#114)Use single underscore for private vars in Python (#92)Improve tracing configuration error reporting (#85)Fix warnings when using mypy 1.8.0. (#89)Remove extra single quote in LdPreload debug log (#79)Contributors: Chris Lalancette, Christophe Bedardtracetools_readReplace all occurences of index.ros.org (#114)Improve tracetools_test and simplify test_tracetools code (#109)Allow tracing tests to be run in parallel with other tests (#95)Contributors: Chris Lalancette, Christophe Bedardtracetools_testReplace all occurences of index.ros.org (#114)Improve tracetools_test and simplify test_tracetools code (#109)Improve assertEventOrder failure output (#106)Allow tracing tests to be run in parallel with other tests (#95)Fix interference between test_tracetools and ros2lifecycle tests (#96)Make tracing test assert messages more descriptive (#93)Fix use of mutable default arg in tracetools_test (#84)Switch to in pure Python packages (#67)Contributors: Chris Lalancette, Christophe Bedardtracetools_traceReplace all occurences of index.ros.org (#114)Improve tracing configuration error reporting (#85)Add a space in between not and parentheses. (#88)Switch to custom lttng-ctl Python bindings (#81)Create start/pause/resume/stop sub-commands for ‘ros2 trace’ (#70)Detect issue with LTTng and Docker and report error when tracing (#66)Contributors: Chris Lalancette, Christophe Bedardtrajectory_msgsClarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris LalancetteturtlesimAdd icon for Jazzy. (#167) (#168) (cherry picked from commit 014955e15a6ac3b1649cbf21e11c8547ebd47af7) Co-authored-by: Marco A. Gutierrez [teleop_turtle_key] update usage string to match keys captured by keyboard (#165) (#166) On windows it will stay uppercase but shouldn’t impact users compared to current situation (cherry picked from commit e2853cac87f0c62db6294e5bc351e5b52fcd1ae1) Co-authored-by: Mikael Arguedas Shorten the callback definition for uncrustify. (#163)Use same QoS for all topic pub/subs (#161)Remove all uses of ament_target_dependencies. (#159)Crop galactic.png and rolling.png to 45x45. (#158)Remove the unused member variable last_state_ (#156)Added common tests (#154)Heavy cleanup of the draw_square tutorial. (#152) * Heavy cleanup of the draw_square tutorial. In particular: 1. Make it conform to the current ROS 2 style. 2. Add in copyright information. 3. Refactor the entire code into a class, which tidies it up quite a bit and removes a bunch of globals. 4. Make sure to wait for the reset to complete before trying to move the turtle.Remove the range constraints from the holonomic parameter. (#150)Add icon (#148)Contributors: Alejandro Hernández Cordero, Chris Lalancette, Jason O’Kane, Yadu, mergify[bot]uncrustify_vendorUpdate to uncrustify 0.78.1 (#37) * Update to uncrustify 0.78.1 * Fix the uncrustify version detection logic. And make sure we are at least 0.78.Switch to ament_cmake_vendor_package (#34)Contributors: Chris Lalancette, Scott K Loganunique_identifier_msgsUpdate to C++17 (#27)Contributors: Chris LalancetteurdfSwitch to target_link_libraries (#36)Contributors: Chris Lalancetteurdf_parser_pluginSwitch to target_link_libraries (#36)Contributors: Chris Lalancettevisualization_msgsRemove references to index.ros.org. (#244)Adds ARROW_STRIP to Marker.msg (#242)Clarify the license. (#241) In particular, every package in this repository is Apache 2.0 licensed except for sensor_msgs_py. So move the CONTRIBUTING.md and LICENSE files down into the individual packages, and make sure that sensor_msgs_py has the correct CONTRIBUTING.md file (it already had the correct LICENSE file).Contributors: Chris Lalancette, Tom Nobleyaml_cpp_vendorRemoved warnigns (#49) (#50) (cherry picked from commit 4b6808fd0f9b0b5e05928c0c8e44fd976a043d33) Co-authored-by: Alejandro Hernández Cordero Upgrade to yaml-cpp 0.8.0 (#48) Co-authored-by: Chris Lalancette Support yaml-cpp >= 0.8.0 (#46)Disable the -Wshadow warning when building under clang. (#45)Switch to ament_cmake_vendor_package (#43)Revamp the extras file to find the correct version. (#42)Contributors: Chris Lalancette, Marco A. Gutierrez, Scott K Logan, Silvio Traversaro, mergify[bot]zstd_vendorUpdated zstd to 1.5.5 (#1617) (#1624)Switch to ament_cmake_vendor_package (#1400)Contributors: Scott K Logan, mergify[bot] \ No newline at end of file diff --git "a/exported_docs/ros2/Launching_nodes\357\203\201.txt" "b/exported_docs/ros2/Launching_nodes\357\203\201.txt" new file mode 100644 index 0000000..2f7ced9 --- /dev/null +++ "b/exported_docs/ros2/Launching_nodes\357\203\201.txt" @@ -0,0 +1,27 @@ +Title: Launching nodes +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Launching-Multiple-Nodes/Launching-Multiple-Nodes.html +Section: Installation +-------------------------------------------------------------------------------- + +Launching nodesGoal:Use a command line tool to launch multiple nodes at once.Tutorial Level:BeginnerTime:5 minutesContentsBackgroundPrerequisitesTasksRunning a Launch File(Optional) Control the Turtlesim NodesSummaryNext stepsBackgroundIn most of the introductory tutorials, you have been opening new terminals for every new node you run. +As you create more complex systems with more and more nodes running simultaneously, opening terminals and reentering configuration details becomes tedious.Launch files allow you to start up and configure a number of executables containing ROS 2 nodes simultaneously.Running a single launch file with theros2launchcommand will start up your entire system - all nodes and their configurations - at once.PrerequisitesBefore starting these tutorials, install ROS 2 by following the instructions on the ROS 2Installationpage.The commands used in this tutorial assume you followed the binary packages installation guide for your operating system (deb packages for Linux). +You can still follow along if you built from source, but the path to your setup files will likely be different. +You also won’t be able to use thesudoaptinstallros--command (used frequently in the beginner level tutorials) if you install from source.If you are using Linux and are not already familiar with the shell,this tutorialwill help.TasksRunning a Launch FileOpen a new terminal and run:ros2 launch turtlesim multisim.launch.pyThis command will run the following launch file:# turtlesim/launch/multisim.launch.pyfromlaunchimportLaunchDescriptionimportlaunch_ros.actionsdefgenerate_launch_description():returnLaunchDescription([launch_ros.actions.Node(namespace="turtlesim1",package='turtlesim',executable='turtlesim_node',output='screen'),launch_ros.actions.Node(namespace="turtlesim2",package='turtlesim',executable='turtlesim_node',output='screen'),])NoteThe launch file above is written in Python, but you can also use XML and YAML to create launch files. +You can see a comparison of these different ROS 2 launch formats inUsing Python, XML, and YAML for ROS 2 Launch Files.This will run two turtlesim nodes:For now, don’t worry about the contents of this launch file. +You can find more information on ROS 2 launch in theROS 2 launch tutorials.(Optional) Control the Turtlesim NodesNow that these nodes are running, you can control them like any other ROS 2 nodes. +For example, you can make the turtles drive in opposite directions by opening up two additional terminals and running the following commands:In the second terminal:ros2 topic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"In the third terminal:ros2 topic pub /turtlesim2/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}"After running these commands, you should see something like the following:SummaryThe significance of what you’ve done so far is that you’ve run two turtlesim nodes with one command. +Once you learn to write your own launch files, you’ll be able to run multiple nodes - and set up their configuration - in a similar way, with theros2launchcommand.For more tutorials on ROS 2 launch files, see themain launch file tutorial page.Next stepsIn the next tutorial,Recording and playing back data, you’ll learn about another helpful tool,ros2bag. + +Code Examples: + +Language: unknown +ros2 launch turtlesim multisim.launch.py + +Language: unknown +# turtlesim/launch/multisim.launch.pyfromlaunchimportLaunchDescriptionimportlaunch_ros.actionsdefgenerate_launch_description():returnLaunchDescription([launch_ros.actions.Node(namespace="turtlesim1",package='turtlesim',executable='turtlesim_node',output='screen'),launch_ros.actions.Node(namespace="turtlesim2",package='turtlesim',executable='turtlesim_node',output='screen'),]) + +Language: unknown +ros2 topic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}" + +Language: unknown +ros2 topic pub /turtlesim2/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}" diff --git "a/exported_docs/ros2/Launch\357\203\201.txt" "b/exported_docs/ros2/Launch\357\203\201.txt" new file mode 100644 index 0000000..66647eb --- /dev/null +++ "b/exported_docs/ros2/Launch\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Launch +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Launch/Launch-Main.html +Section: Installation +-------------------------------------------------------------------------------- + +LaunchROS 2 Launch files allow you to start up and configure a number of executables containing ROS 2 nodes simultaneously.Creating a launch file.Learn how to create a launch file that will start up nodes and their configurations all at once.Launching and monitoring multiple nodes.Get a more advanced overview of how launch files work.Using substitutions.Use substitutions to provide more flexibility when describing reusable launch files.Using event handlers.Use event handlers to monitor the state of processes or to define a complex set of rules that can be used to dynamically modify the launch file.Managing large projects.Structure launch files for large projects so they may be reused as much as possible in different situations. +See usage examples of different launch tools like parameters, YAML files, remappings, namespaces, default arguments, and RViz configs.NoteIf you are coming from ROS 1, you can use theROS Launch Migration guideto help you migrate your launch files to ROS 2. \ No newline at end of file diff --git "a/exported_docs/ros2/Logging\357\203\201.txt" "b/exported_docs/ros2/Logging\357\203\201.txt" new file mode 100644 index 0000000..058aab7 --- /dev/null +++ "b/exported_docs/ros2/Logging\357\203\201.txt" @@ -0,0 +1,187 @@ +Title: Logging +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos/Logging-and-logger-configuration.html +Section: Installation +-------------------------------------------------------------------------------- + +LoggingTable of ContentsUsing log statements in codeBasic loggingLogging only the first timeLogging all but the first timeLogging throttledLogging throttled all but the first timeLogging demoLogging directory configurationLogger level configuration: programmaticallyLogger level configuration: externallyUsing the logger config componentLogger level configuration: command lineConsole output formattingConsole output colorizingDefault stream for console outputLine buffered console outputSetting the log file name prefixSeethe logging pagefor details on available functionality.Using log statements in codeBasic loggingThe following code will output a log message from a ROS 2 node atDEBUGseverity:C++Python// printf styleRCLCPP_DEBUG(node->get_logger(),"My log message %d",4);// C++ stream styleRCLCPP_DEBUG_STREAM(node->get_logger(),"My log message "<<4);node.get_logger().debug('My log message%d'%(4))Note that in both cases, no trailing newline is added, as the logging infrastructure will automatically add one.Logging only the first timeThe following code will output a log message from a ROS 2 node atINFOseverity, but only the first time it is hit:C++Python// printf styleRCLCPP_INFO_ONCE(node->get_logger(),"My log message %d",4);// C++ stream styleRCLCPP_INFO_STREAM_ONCE(node->get_logger(),"My log message "<<4);num=4node.get_logger().info(f'My log message{num}',once=True)Logging all but the first timeThe following code will output a log message from a ROS 2 node atWARNseverity, but not the very first time it is hit:C++Python// printf styleRCLCPP_WARN_SKIPFIRST(node->get_logger(),"My log message %d",4);// C++ stream styleRCLCPP_WARN_STREAM_SKIPFIRST(node->get_logger(),"My log message "<<4);num=4node.get_logger().warning('My log message{0}'.format(num),skip_first=True)Logging throttledThe following code will output a log message from a ROS 2 node atERRORseverity, but no more than once per second.The interval parameter specifying milliseconds between messages should have an integer data type so it can be converted to arcutils_duration_value_t(anint64_t):C++Python// printf styleRCLCPP_ERROR_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message %d",4);// C++ stream styleRCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message "<<4);// For now, use the nanoseconds() method to use an existing rclcpp::Duration value, see https://github.com/ros2/rclcpp/issues/1929RCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(),*node->get_clock(),msg_interval.nanoseconds()/1000000,"My log message "<<4);num=4node.get_logger().error(f'My log message{num}',throttle_duration_sec=1)Logging throttled all but the first timeThe following code will output a log message from a ROS 2 node atDEBUGseverity, no more than once per second, skipping the very first time it is hit:C++Python// printf styleRCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message %d",4);RCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message "<<4);num=4node.get_logger().debug(f'My log message{num}',skip_first=True,throttle_duration_sec=1.0)Logging demoIn thisdemo, different types of log calls are shown and the severity level of different loggers is configured locally and externally.Start the demo with:ros2runlogging_demologging_demo_mainOver time you will see output from various log calls with different properties. +To start with you will only see output from log calls with severityINFOand above (WARN,ERROR,FATAL). +Note that the first message will only be logged once, though the line is reached on each iteration, as that is a property of the log call used for that message.Logging directory configurationThe logging directory can be configured through two environment variables:ROS_LOG_DIRandROS_HOME. +The logic is as follows:Use$ROS_LOG_DIRifROS_LOG_DIRis set and not empty.Otherwise, use$ROS_HOME/log, using~/.rosforROS_HOMEif not set or if empty.For example, to set the logging directory to~/my_logs:LinuxmacOSWindowsexportROS_LOG_DIR=~/my_logs +ros2runlogging_demologging_demo_mainexportROS_LOG_DIR=~/my_logs +ros2runlogging_demologging_demo_mainset"ROS_LOG_DIR=~/my_logs"ros2runlogging_demologging_demo_mainYou will then find the logs under~/my_logs/.Alternatively, you can setROS_HOMEand the logging directory will be relative to it ($ROS_HOME/log).ROS_HOMEis intended to be used by anything that needs a base directory. +Note thatROS_LOG_DIRhas to be either unset or empty. +For example, withROS_HOMEset to~/my_ros_home:LinuxmacOSWindowsexportROS_HOME=~/my_ros_home +ros2runlogging_demologging_demo_mainexportROS_HOME=~/my_ros_home +ros2runlogging_demologging_demo_mainset"ROS_HOME=~/my_ros_home"ros2runlogging_demologging_demo_mainYou will then find the logs under~/my_ros_home/log/.Logger level configuration: programmaticallyAfter 10 iterations the level of the logger will be set toDEBUG, which will cause additional messages to be logged.Some of these debug messages cause additional functions/expressions to be evaluated, which were previously skipped asDEBUGlog calls were not enabled. +Seethe source codeof the demo for further explanation of the calls used, and see the rclcpp logging documentation for a full list of supported logging calls.Logger level configuration: externallyROS 2 nodes have services available to configure the logging level externally at runtime. +These services are disabled by default. +The following code shows how to enable the logger service while creating the node.C++Python// Create a node with logger service enabledautonode=std::make_shared("NodeWithLoggerService",rclcpp::NodeOptions().enable_logger_service(true))# Create a node with logger service enablednode=Node('NodeWithLoggerService',enable_logger_service=True)If you run one of the nodes as configured above, you will find 2 services when runningros2servicelist:$ros2servicelist +... +/NodeWithLoggerService/get_logger_levels +/NodeWithLoggerService/set_logger_levels +...get_logger_levelsUse this service to get logger levels for specified logger names.Runros2servicecallto get logger levels forNodeWithLoggerServiceandrcl.$ros2servicecall/NodeWithLoggerService/get_logger_levelsrcl_interfaces/srv/GetLoggerLevels'{names: ["NodeWithLoggerService", "rcl"]}'requester:makingrequest:rcl_interfaces.srv.GetLoggerLevels_Request(names=['NodeWithLoggerService','rcl'])response: +rcl_interfaces.srv.GetLoggerLevels_Response(levels=[rcl_interfaces.msg.LoggerLevel(name='NodeWithLoggerService',level=0),rcl_interfaces.msg.LoggerLevel(name='rcl',level=0)])set_logger_levelsUse this service to set logger levels for specified logger names.Runros2servicecallto set logger levels forNodeWithLoggerServiceandrcl.$ros2servicecall/NodeWithLoggerService/set_logger_levelsrcl_interfaces/srv/SetLoggerLevels'{levels: [{name: "NodeWithLoggerService", level: 20}, {name: "rcl", level: 10}]}'requester:makingrequest:rcl_interfaces.srv.SetLoggerLevels_Request(levels=[rcl_interfaces.msg.LoggerLevel(name='NodeWithLoggerService',level=20),rcl_interfaces.msg.LoggerLevel(name='rcl',level=10)])response: +rcl_interfaces.srv.SetLoggerLevels_Response(results=[rcl_interfaces.msg.SetLoggerLevelsResult(successful=True,reason=''),rcl_interfaces.msg.SetLoggerLevelsResult(successful=True,reason='')])There is also demo code showing how to set or get the logger level via the logger service.rclcpp:demo code$ros2rundemo_nodes_cppuse_logger_servicerclpy:demo code$ros2rundemo_nodes_pyuse_logger_serviceWarningCurrently, there is a limitation thatget_logger_levelsandset_logger_levelsservices are not thread-safe. +This means that you need to ensure that only one thread is calling the services at a time. +Please see the details inhttps://github.com/ros2/rcutils/issues/397Using the logger config componentThe server that responds to the logger configuration requests has been developed as a component so that it may be added to an existing composition-based system. +For example, if you are usinga container to run your nodes, to be able to configure your loggers you only need to request that it additionally load thelogging_demo::LoggerConfigcomponent into the container.As an example, if you want to debug thecomposition::Talkerdemo, you can start the talker as normal with:Shell 1:ros2runrclcpp_componentscomponent_containerShell 2:ros2componentload/ComponentManagercompositioncomposition::TalkerAnd then when you want to enable debug logging, load theLoggerConfigcomponent with:Shell 2ros2componentload/ComponentManagerlogging_demologging_demo::LoggerConfigAnd finally, configure all unset loggers to the debug severity by addressing the empty-named logger. +Note that loggers that have been specifically configured to use a particular severity will not be affected by this call.Shell 2:ros2servicecall/config_loggerlogging_demo/srv/ConfigLogger"{logger_name: '', level: DEBUG}"You should see debug output from any previously unset loggers in the process start to appear, including from the ROS 2 core.Logger level configuration: command lineAs of the Bouncy ROS 2 release, the severity level for loggers that have not had their severity set explicitly can be configured from the command line. +Restart the demo including the following command line argument:ros2runlogging_demologging_demo_main--ros-args--log-leveldebugThis configures the default severity for any unset logger to the debug severity level. +You should see debug output from loggers from the demo itself and from the ROS 2 core.The severity level for individual loggers can be configured from the command-line. +Restart the demo including the following command line arguments:ros2runlogging_demologging_demo_main--ros-args--log-levellogger_usage_demo:=debugConsole output formattingIf you would like more or less verbose formatting, you can use theRCUTILS_CONSOLE_OUTPUT_FORMATenvironment variable. +For example, to additionally get the timestamp and location of the log calls, stop the demo and restart it with the environment variable set:LinuxmacOSWindowsexportRCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"ros2runlogging_demologging_demo_mainexportRCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"ros2runlogging_demologging_demo_mainset"RCUTILS_CONSOLE_OUTPUT_FORMAT=[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"ros2runlogging_demologging_demo_mainYou should see the timestamp in seconds and the function name, filename and line number additionally printed with each message.For more information on configuring the console logger formatting, see thelogger console configurationConsole output colorizingBy default, the output is colorized when it’s targeting a terminal. +If you would like to force enabling or disabling it, you can use theRCUTILS_COLORIZED_OUTPUTenvironment variable. +For example:LinuxmacOSWindowsexportRCUTILS_COLORIZED_OUTPUT=0# 1 for forcing itros2runlogging_demologging_demo_mainexportRCUTILS_COLORIZED_OUTPUT=0# 1 for forcing itros2runlogging_demologging_demo_mainset"RCUTILS_COLORIZED_OUTPUT=0"::1forforcingit +ros2runlogging_demologging_demo_mainYou should see that debug, warn, error and fatal logs aren’t colorized now.NoteIn Linux and MacOS forcing colorized output means that if you redirect the output to a file, the ansi escape color codes will appear on it. +In windows the colorization method relies on console APIs. +If it is forced you will get a new warning saying that colorization failed. +The default behavior already checks if the output is a console or not, so forcing colorization is not recommended.Default stream for console outputIn Foxy and later, the output from all debug levels goes to stderr by default. It is possible to force all output to go to stdout by setting theRCUTILS_LOGGING_USE_STDOUTenvironment variable to1. +For example:LinuxmacOSWindowsexportRCUTILS_LOGGING_USE_STDOUT=1exportRCUTILS_LOGGING_USE_STDOUT=1set"RCUTILS_LOGGING_USE_STDOUT=1"Line buffered console outputBy default, all logging output is unbuffered. +You can force it to be buffered by setting theRCUTILS_LOGGING_BUFFERED_STREAMenvironment variable to 1. +For example:LinuxmacOSWindowsexportRCUTILS_LOGGING_BUFFERED_STREAM=1exportRCUTILS_LOGGING_BUFFERED_STREAM=1set"RCUTILS_LOGGING_BUFFERED_STREAM=1"Then run:ros2runlogging_demologging_demo_mainSetting the log file name prefixBy default, the log file name is based on the executable file name followed by process ID and system timestamp on file creation. +You can change the log file name prefix to one of your choice using the--log-file-namecommand line argument:ros2rundemo_nodes_cpptalker--ros-args--log-file-namefilenameThis configures the log file name prefix tofilename, instead of the executable file name (which istalkerin this case). + +Code Examples: + +Language: unknown +// printf styleRCLCPP_DEBUG(node->get_logger(),"My log message %d",4);// C++ stream styleRCLCPP_DEBUG_STREAM(node->get_logger(),"My log message "<<4); + +Language: unknown +node.get_logger().debug('My log message%d'%(4)) + +Language: unknown +// printf styleRCLCPP_INFO_ONCE(node->get_logger(),"My log message %d",4);// C++ stream styleRCLCPP_INFO_STREAM_ONCE(node->get_logger(),"My log message "<<4); + +Language: unknown +num=4node.get_logger().info(f'My log message{num}',once=True) + +Language: unknown +// printf styleRCLCPP_WARN_SKIPFIRST(node->get_logger(),"My log message %d",4);// C++ stream styleRCLCPP_WARN_STREAM_SKIPFIRST(node->get_logger(),"My log message "<<4); + +Language: unknown +num=4node.get_logger().warning('My log message{0}'.format(num),skip_first=True) + +Language: unknown +// printf styleRCLCPP_ERROR_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message %d",4);// C++ stream styleRCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message "<<4);// For now, use the nanoseconds() method to use an existing rclcpp::Duration value, see https://github.com/ros2/rclcpp/issues/1929RCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(),*node->get_clock(),msg_interval.nanoseconds()/1000000,"My log message "<<4); + +Language: unknown +num=4node.get_logger().error(f'My log message{num}',throttle_duration_sec=1) + +Language: unknown +// printf styleRCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message %d",4);RCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(),*node->get_clock(),1000,"My log message "<<4); + +Language: unknown +num=4node.get_logger().debug(f'My log message{num}',skip_first=True,throttle_duration_sec=1.0) + +Language: unknown +ros2runlogging_demologging_demo_main + +Language: unknown +exportROS_LOG_DIR=~/my_logs +ros2runlogging_demologging_demo_main + +Language: unknown +exportROS_LOG_DIR=~/my_logs +ros2runlogging_demologging_demo_main + +Language: unknown +set"ROS_LOG_DIR=~/my_logs"ros2runlogging_demologging_demo_main + +Language: unknown +exportROS_HOME=~/my_ros_home +ros2runlogging_demologging_demo_main + +Language: unknown +exportROS_HOME=~/my_ros_home +ros2runlogging_demologging_demo_main + +Language: unknown +set"ROS_HOME=~/my_ros_home"ros2runlogging_demologging_demo_main + +Language: unknown +// Create a node with logger service enabledautonode=std::make_shared("NodeWithLoggerService",rclcpp::NodeOptions().enable_logger_service(true)) + +Language: unknown +# Create a node with logger service enablednode=Node('NodeWithLoggerService',enable_logger_service=True) + +Language: unknown +$ros2servicelist +... +/NodeWithLoggerService/get_logger_levels +/NodeWithLoggerService/set_logger_levels +... + +Language: unknown +$ros2servicecall/NodeWithLoggerService/get_logger_levelsrcl_interfaces/srv/GetLoggerLevels'{names: ["NodeWithLoggerService", "rcl"]}'requester:makingrequest:rcl_interfaces.srv.GetLoggerLevels_Request(names=['NodeWithLoggerService','rcl'])response: +rcl_interfaces.srv.GetLoggerLevels_Response(levels=[rcl_interfaces.msg.LoggerLevel(name='NodeWithLoggerService',level=0),rcl_interfaces.msg.LoggerLevel(name='rcl',level=0)]) + +Language: unknown +$ros2servicecall/NodeWithLoggerService/set_logger_levelsrcl_interfaces/srv/SetLoggerLevels'{levels: [{name: "NodeWithLoggerService", level: 20}, {name: "rcl", level: 10}]}'requester:makingrequest:rcl_interfaces.srv.SetLoggerLevels_Request(levels=[rcl_interfaces.msg.LoggerLevel(name='NodeWithLoggerService',level=20),rcl_interfaces.msg.LoggerLevel(name='rcl',level=10)])response: +rcl_interfaces.srv.SetLoggerLevels_Response(results=[rcl_interfaces.msg.SetLoggerLevelsResult(successful=True,reason=''),rcl_interfaces.msg.SetLoggerLevelsResult(successful=True,reason='')]) + +Language: unknown +$ros2rundemo_nodes_cppuse_logger_service + +Language: unknown +$ros2rundemo_nodes_pyuse_logger_service + +Language: unknown +ros2runrclcpp_componentscomponent_container + +Language: unknown +ros2componentload/ComponentManagercompositioncomposition::Talker + +Language: unknown +ros2componentload/ComponentManagerlogging_demologging_demo::LoggerConfig + +Language: unknown +ros2servicecall/config_loggerlogging_demo/srv/ConfigLogger"{logger_name: '', level: DEBUG}" + +Language: unknown +ros2runlogging_demologging_demo_main--ros-args--log-leveldebug + +Language: unknown +ros2runlogging_demologging_demo_main--ros-args--log-levellogger_usage_demo:=debug + +Language: unknown +exportRCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"ros2runlogging_demologging_demo_main + +Language: unknown +exportRCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"ros2runlogging_demologging_demo_main + +Language: unknown +set"RCUTILS_CONSOLE_OUTPUT_FORMAT=[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"ros2runlogging_demologging_demo_main + +Language: unknown +exportRCUTILS_COLORIZED_OUTPUT=0# 1 for forcing itros2runlogging_demologging_demo_main + +Language: unknown +exportRCUTILS_COLORIZED_OUTPUT=0# 1 for forcing itros2runlogging_demologging_demo_main + +Language: unknown +set"RCUTILS_COLORIZED_OUTPUT=0"::1forforcingit +ros2runlogging_demologging_demo_main + +Language: unknown +exportRCUTILS_LOGGING_USE_STDOUT=1 + +Language: unknown +exportRCUTILS_LOGGING_USE_STDOUT=1 + +Language: unknown +set"RCUTILS_LOGGING_USE_STDOUT=1" + +Language: unknown +exportRCUTILS_LOGGING_BUFFERED_STREAM=1 + +Language: unknown +exportRCUTILS_LOGGING_BUFFERED_STREAM=1 + +Language: unknown +set"RCUTILS_LOGGING_BUFFERED_STREAM=1" + +Language: unknown +ros2runlogging_demologging_demo_main + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--log-file-namefilename diff --git "a/exported_docs/ros2/Maintain_source_checkout\357\203\201.txt" "b/exported_docs/ros2/Maintain_source_checkout\357\203\201.txt" new file mode 100644 index 0000000..c2931fb --- /dev/null +++ "b/exported_docs/ros2/Maintain_source_checkout\357\203\201.txt" @@ -0,0 +1,71 @@ +Title: Maintain source checkout +URL: https://docs.ros.org/en/jazzy/Installation/Maintaining-a-Source-Checkout.html +Section: Installation +-------------------------------------------------------------------------------- + +Maintain source checkoutNoteFor instructions on maintaining a source checkout of thelatest development versionof ROS 2, refer toMaintaining a source checkout of ROS 2 RollingUpdate your repository listLatest ROS 2 Jazzy branchesUpdate your repositoriesDownload the new source codeRebuild your workspaceInspect your source checkoutIf you have installed ROS 2 from source, there may have been changes made to the source code since the time that you checked it out. +To keep your source checkout up to date, you will have to periodically update yourros2.reposfile, download the latest sources, and rebuild your workspace.Update your repository listEach ROS 2 release includes aros2.reposfile that contains the list of repositories and their version for that release.Latest ROS 2 Jazzy branchesIf you wish to checkout the latest code for ROS 2 Jazzy, you can get the relevant repository list by running:LinuxmacOSWindowscd~/ros2_jazzy +mv-iros2.reposros2.repos.old +wgethttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.reposcd~/ros2_jazzy +mv-iros2.reposros2.repos.old +wgethttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos# CMDcd\dev\ros2_jazzy +curl-skhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos-oros2.repos# PowerShellcd\dev\ros2_jazzy +curlhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos-oros2.reposUpdate your repositoriesYou will notice that in theros2.reposfile, each repository has aversionassociated with it that points to a particular commit hash, tag, or branch name. +It is possible that these versions refer to new tags/branches that your local copy of the repositories will not recognize as they are out-of-date. +Because of this, you should update the repositories that you have already checked out with the following command:vcscustom--argsremoteupdateDownload the new source codeYou should now be able to download the sources associated with the new repository list with:LinuxmacOSWindowsvcsimportsrcmy_ros2.reposcd~/ros2_jazzy +vcsexportsrc>my_ros2.reposcd\dev\ros2_jazzy +vcsexportsrc>my_ros2.reposThismy_ros2.reposfile can then be shared with others so that they can reproduce the state of the repositories in your workspace. + +Code Examples: + +Language: unknown +cd~/ros2_jazzy +mv-iros2.reposros2.repos.old +wgethttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos + +Language: unknown +cd~/ros2_jazzy +mv-iros2.reposros2.repos.old +wgethttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos + +Language: unknown +# CMDcd\dev\ros2_jazzy +curl-skhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos-oros2.repos# PowerShellcd\dev\ros2_jazzy +curlhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repos-oros2.repos + +Language: unknown +vcscustom--argsremoteupdate + +Language: unknown +vcsimportsrcmy_ros2.repos + +Language: unknown +cd~/ros2_jazzy +vcsexportsrc>my_ros2.repos + +Language: unknown +cd\dev\ros2_jazzy +vcsexportsrc>my_ros2.repos diff --git "a/exported_docs/ros2/Managing_Dependencies_with_rosdep\357\203\201.txt" "b/exported_docs/ros2/Managing_Dependencies_with_rosdep\357\203\201.txt" new file mode 100644 index 0000000..26fd343 --- /dev/null +++ "b/exported_docs/ros2/Managing_Dependencies_with_rosdep\357\203\201.txt" @@ -0,0 +1,55 @@ +Title: Managing Dependencies with rosdep +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Rosdep.html +Section: Installation +-------------------------------------------------------------------------------- + +Managing Dependencies with rosdepTable of ContentsWhat is rosdep?A little about package.xml filesHow does rosdep work?How do I know what keys to put in my package.xml?What if my library isn’t in rosdistro?How do I use the rosdep tool?rosdep installationrosdep operationGoal:Manage external dependencies usingrosdep.Tutorial level:IntermediateTime:5 minutesThis tutorial will explain how to manage external dependencies usingrosdep.WarningCurrently rosdep only works on Linux and macOS; Windows is not supported. +There are long-term plans to add support for Windows tohttps://github.com/ros-infrastructure/rosdep.What is rosdep?rosdepis a dependency management utility that can work with packages and external libraries. +It is a command-line utility for identifying and installing dependencies to build or install a package.rosdepisnota package manager in its own right; it is a meta-package manager that uses its own knowledge of the system and the dependencies to find the appropriate package to install on a particular platform. +The actual installation is done using the system package manager (e.g.apton Debian/Ubuntu,dnfon Fedora/RHEL, etc).It is most often invoked before building a workspace, where it is used to install the dependencies of the packages within that workspace.It has the ability to work over a single package or over a directory of packages (e.g. workspace).NoteWhile the name suggests it is for ROS,rosdepis semi-agnostic to ROS. +You can utilize this powerful tool in non-ROS software projects by installing it as a standalone Python package. +Successfully runningrosdeprelies onrosdepkeysto be available, which can be downloaded from a public git repository with a few simple commands.A little about package.xml filesThepackage.xmlis the file in your software whererosdepfinds the set of dependencies. +It is important that the list of dependencies in thepackage.xmlis complete and correct, which allows all of the tooling to determine the packages dependencies. +Missing or incorrect dependencies can lead to users not being able to use your package, to packages in a workspace being built out-of-order, and to packages not being able to be released.The dependencies in thepackage.xmlfile are generally referred to as “rosdep keys”. +These dependencies are manually populated in thepackage.xmlfile by the package’s creators and should be an exhaustive list of any non-builtin libraries and packages it requires.These are represented in the following tags (seeREP-149for the full specification):These are dependencies that should be provided at both build time and run time for your package. +For C++ packages, if in doubt, use this tag. +Pure Python packages generally don’t have a build phase, so should never use this and should useinstead.If you only use a particular dependency for building your package, and not at execution time, you can use thetag.With this type of dependency, an installed binary of your package does not require that particular package to be installed.However, that can create a problem if your package exports a header that includes a header from this dependency. +In that case you also need a.If you export a header that includes a header from a dependency, it will be needed by other packages thaton yours. +This mainly applies to headers and CMake configuration files. +Library packages referenced by libraries you export should normally specify, because they are also needed at execution time.This tag declares dependencies for shared libraries, executables, Python modules, launch scripts and other files required when running your package.This tag declares dependencies needed only by tests. +Dependencies here shouldnotbe duplicated with keys specified by,, or.How does rosdep work?rosdepwill check forpackage.xmlfiles in its path or for a specific package and find the rosdep keys stored within. +These keys are then cross-referenced against a central index to find the appropriate ROS package or software library in various package managers. +Finally, once the packages are found, they are installed and ready to go!rosdepworks by retrieving the central index on to your local machine so that it doesn’t have to access the network every time it runs (on Debian/Ubuntu the configuration for it is stored in/etc/ros/rosdep/sources.list.d/20-default.list).The central index is known asrosdistro, whichmay be found online. +We’ll explore that more in the next section.How do I know what keys to put in my package.xml?Great question, I’m glad you asked!If the package you want to depend in your package is ROS-based, AND has been released into the ROS ecosystem[1], e.g.nav2_bt_navigator, you may simply use the name of the package. You can find a list of all released ROS packages inhttps://github.com/ros/rosdistroat/distribution.yaml(e.g.humble/distribution.yaml) for your given ROS distribution.If you want to depend on a non-ROS package, something often called “system dependencies”, you will need to find the keys for a particular library. In general, there are two files of interest:rosdep/base.yamlcontains theaptsystem dependenciesrosdep/python.yamlcontains the Python dependenciesTo find a key, search for your library in these files and find the name. +This is the key to put in apackage.xmlfile.For example, imagine a package had a dependency ondoxygenbecause it is a great piece of software that cares about quality documentation (hint hint). +We would searchrosdep/base.yamlfordoxygenand come across:doxygen:arch:[doxygen]debian:[doxygen]fedora:[doxygen]freebsd:[doxygen]gentoo:[app-doc/doxygen]macports:[doxygen]nixos:[doxygen]openembedded:[doxygen@meta-oe]opensuse:[doxygen]rhel:[doxygen]ubuntu:[doxygen]That means our rosdep key isdoxygen, which would resolve to those various names in different operating system’s package managers for installation.What if my library isn’t in rosdistro?If your library isn’t inrosdistro, you can experience the greatness that is open-source software development: you can add it yourself! +Pull requests for rosdistro are typically merged well within a week.Detailed instructions may be found herefor how to contribute new rosdep keys. +If for some reason these may not be contributed openly, it is possible to fork rosdistro and maintain a alternate index for use.How do I use the rosdep tool?rosdep installationIf you are usingrosdepwith ROS, it is conveniently packaged along with the ROS distribution. +This is the recommended way to getrosdep. +You can install it with:apt-getinstallpython3-rosdepNoteOn Debian and Ubuntu, there is another, similarly named package calledpython3-rosdep2. +If that package is installed, make sure to remove it before installingpython3-rosdep.If you are usingrosdepoutside of ROS, the system package may not be available. +In that case, you can install it directly fromhttps://pypi.org:pipinstallrosdeprosdep operationNow that we have some understanding ofrosdep,package.xml, androsdistro, we’re ready to use the utility itself! +Firstly, if this is the first time usingrosdep, it must be initialized via:sudorosdepinit +rosdepupdateThis will initialize rosdep andupdatewill update the locally cached rosdistro index. +It is a good idea toupdaterosdep on occasion to get the latest index.Finally, we can runrosdepinstallto install dependencies. +Typically, this is run over a workspace with many packages in a single call to install all dependencies. +A call for that would appear as the following, if in the root of the workspace with directorysrccontaining source code.rosdepinstall--from-pathssrc-y--ignore-srcBreaking that down:--from-pathssrcspecifies the path to check forpackage.xmlfiles to resolve keys for-ymeans to default yes to all prompts from the package manager to install without prompts--ignore-srcmeans to ignore installing dependencies, even if a rosdep key exists, if the package itself is also in the workspace.There are additional arguments and options available. +Userosdep-hto see them, or look at the more complete documentation for rosdep athttp://docs.ros.org/en/independent/api/rosdep/html/.[1]“released into the ROS ecosystem” means the package is listed in one or more of the/distribution.yamldirectories in therosdistro database. + +Code Examples: + +Language: unknown +doxygen:arch:[doxygen]debian:[doxygen]fedora:[doxygen]freebsd:[doxygen]gentoo:[app-doc/doxygen]macports:[doxygen]nixos:[doxygen]openembedded:[doxygen@meta-oe]opensuse:[doxygen]rhel:[doxygen]ubuntu:[doxygen] + +Language: unknown +apt-getinstallpython3-rosdep + +Language: unknown +pipinstallrosdep + +Language: unknown +sudorosdepinit +rosdepupdate + +Language: unknown +rosdepinstall--from-pathssrc-y--ignore-src diff --git "a/exported_docs/ros2/Managing_large_projects\357\203\201.txt" "b/exported_docs/ros2/Managing_large_projects\357\203\201.txt" new file mode 100644 index 0000000..96815a4 --- /dev/null +++ "b/exported_docs/ros2/Managing_large_projects\357\203\201.txt" @@ -0,0 +1,109 @@ +Title: Managing large projects +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Launch/Using-ROS2-Launch-For-Large-Projects.html +Section: Installation +-------------------------------------------------------------------------------- + +Managing large projectsGoal:Learn best practices of managing large projects using ROS 2 launch files.Tutorial level:IntermediateTime:20 minutesContentsBackgroundPrerequisitesIntroductionWriting launch files1 Top-level organization2 Parameters2.1 Setting parameters in the launch file2.2 Loading parameters from YAML file2.3 Using wildcards in YAML files3 Namespaces4 Reusing nodes5 Parameter overrides6 Remapping7 Config files8 Environment VariablesRunning launch files1 Update setup.py2 Build and runSummaryBackgroundThis tutorial describes some tips for writing launch files for large projects. +The focus is on how to structure launch files so they may be reused as much as possible in different situations. +Additionally, it covers usage examples of different ROS 2 launch tools, like parameters, YAML files, remappings, namespaces, default arguments, and RViz configs.PrerequisitesThis tutorial uses theturtlesimandturtle_tf2_pypackages. +This tutorial also assumes you havecreated a new packageof build typeament_pythoncalledlaunch_tutorial.IntroductionLarge applications on a robot typically involve several interconnected nodes, each of which can have many parameters. +Simulation of multiple turtles in the turtle simulator can serve as a good example. +The turtle simulation consists of multiple turtle nodes, the world configuration, and the TF broadcaster and listener nodes. +Between all of the nodes, there are a large number of ROS parameters that affect the behavior and appearance of these nodes. +ROS 2 launch files allow us to start all nodes and set corresponding parameters in one place. +By the end of a tutorial, you will build thelaunch_turtlesim_launch.pylaunch file in thelaunch_tutorialpackage. +This launch file will bring up different nodes responsible for the simulation of two turtlesim simulations, starting TF broadcasters and listener, loading parameters, and launching an RViz configuration. +In this tutorial, we’ll go over this launch file and all related features used.Writing launch files1 Top-level organizationOne of the aims in the process of writing launch files should be making them as reusable as possible. +This could be done by clustering related nodes and configurations into separate launch files. +Afterwards, a top-level launch file dedicated to a specific configuration could be written. +This would allow moving between identical robots to be done without changing the launch files at all. +Even a change such as moving from a real robot to a simulated one can be done with only a few changes.We will now go over the top-level launch file structure that makes this possible. +Firstly, we will create a launch file that will call separate launch files. +To do this, let’s create alaunch_turtlesim_launch.pyfile in the/launchfolder of ourlaunch_tutorialpackage.importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcedefgenerate_launch_description():turtlesim_world_1=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_world_1_launch.py']))turtlesim_world_2=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_world_2_launch.py']))broadcaster_listener_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/broadcaster_listener_launch.py']),launch_arguments={'target_frame':'carrot1'}.items(),)mimic_node=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/mimic_launch.py']))fixed_frame_node=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/fixed_broadcaster_launch.py']))rviz_node=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_rviz_launch.py']))returnLaunchDescription([turtlesim_world_1,turtlesim_world_2,broadcaster_listener_nodes,mimic_node,fixed_frame_node,rviz_node])This launch file includes a set of other launch files. +Each of these included launch files contains nodes, parameters, and possibly, nested includes, which pertain to one part of the system. +To be exact, we launch two turtlesim simulation worlds, TF broadcaster, TF listener, mimic, fixed frame broadcaster, and RViz nodes.NoteDesign Tip: Top-level launch files should be short, consist of includes to other files corresponding to subcomponents of the application, and commonly changed parameters.Writing launch files in the following manner makes it easy to swap out one piece of the system, as we’ll see later. +However, there are cases when some nodes or launch files have to be launched separately due to performance and usage reasons.NoteDesign tip: Be aware of the tradeoffs when deciding how many top-level launch files your application requires.2 Parameters2.1 Setting parameters in the launch fileWe will begin by writing a launch file that will start our first turtlesim simulation. +First, create a new file calledturtlesim_world_1_launch.py.fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfiguration,TextSubstitutionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():background_r_launch_arg=DeclareLaunchArgument('background_r',default_value=TextSubstitution(text='0'))background_g_launch_arg=DeclareLaunchArgument('background_g',default_value=TextSubstitution(text='84'))background_b_launch_arg=DeclareLaunchArgument('background_b',default_value=TextSubstitution(text='122'))returnLaunchDescription([background_r_launch_arg,background_g_launch_arg,background_b_launch_arg,Node(package='turtlesim',executable='turtlesim_node',name='sim',parameters=[{'background_r':LaunchConfiguration('background_r'),'background_g':LaunchConfiguration('background_g'),'background_b':LaunchConfiguration('background_b'),}]),])This launch file starts theturtlesim_nodenode, which starts the turtlesim simulation, with simulation configuration parameters that are defined and passed to the nodes.2.2 Loading parameters from YAML fileIn the second launch, we will start a second turtlesim simulation with a different configuration. +Now create aturtlesim_world_2_launch.pyfile.importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():config=os.path.join(get_package_share_directory('launch_tutorial'),'config','turtlesim.yaml')returnLaunchDescription([Node(package='turtlesim',executable='turtlesim_node',namespace='turtlesim2',name='sim',parameters=[config])])This launch file will launch the sameturtlesim_nodewith parameter values that are loaded directly from the YAML configuration file. +Defining arguments and parameters in YAML files make it easy to store and load a large number of variables. +In addition, YAML files can be easily exported from the currentros2paramlist. +To learn how to do that, refer to theUnderstand parameterstutorial.Let’s now create a configuration file,turtlesim.yaml, in the/configfolder of our package, which will be loaded by our launch file./turtlesim2/sim:ros__parameters:background_b:255background_g:86background_r:150To learn more about using parameters and using YAML files, take a look at theUnderstand parameterstutorial.2.3 Using wildcards in YAML filesThere are cases when we want to set the same parameters in more than one node. +These nodes could have different namespaces or names but still have the same parameters. +Defining separate YAML files that explicitly define namespaces and node names is not efficient. +A solution is to use wildcard characters, which act as substitutions for unknown characters in a text value, to apply parameters to several different nodes.Now let’s create a newturtlesim_world_3_launch.pyfile similar toturtlesim_world_2_launch.pyto include one moreturtlesim_nodenode....Node(package='turtlesim',executable='turtlesim_node',namespace='turtlesim3',name='sim',parameters=[config])Loading the same YAML file, however, will not affect the appearance of the third turtlesim world. +The reason is that its parameters are stored under another namespace as shown below:/turtlesim3/sim:background_bbackground_gbackground_rTherefore, instead of creating a new configuration for the same node that use the same parameters, we can use wildcards syntax./**will assign all the parameters in every node, despite differences in node names and namespaces.We will now update theturtlesim.yaml, in the/configfolder in the following manner:/**:ros__parameters:background_b:255background_g:86background_r:150Now include theturtlesim_world_3_launch.pylaunch description in our main launch file. +Using that configuration file in our launch descriptions will assignbackground_b,background_g, andbackground_rparameters to specified values inturtlesim3/simandturtlesim2/simnodes.3 NamespacesAs you may have noticed, we have defined the namespace for the turlesim world in theturtlesim_world_2_launch.pyfile. +Unique namespaces allow the system to start two similar nodes without node name or topic name conflicts.namespace='turtlesim2',However, if the launch file contains a large number of nodes, defining namespaces for each of them can become tedious. +To solve that issue, thePushROSNamespaceaction can be used to define the global namespace for each launch file description. +Every nested node will inherit that namespace automatically.AttentionPushROSNamespace has to be the first Action in the list for the following actions to apply the namespaceTo do that, firstly, we need to remove thenamespace='turtlesim2'line from theturtlesim_world_2_launch.pyfile. +Afterwards, we need to update thelaunch_turtlesim_launch.pyto include the following lines:fromlaunch.actionsimportGroupActionfromlaunch_ros.actionsimportPushROSNamespace...turtlesim_world_2=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_world_2_launch.py']))turtlesim_world_2_with_namespace=GroupAction(actions=[PushROSNamespace('turtlesim2'),turtlesim_world_2,])Finally, we replace theturtlesim_world_2toturtlesim_world_2_with_namespacein thereturnLaunchDescriptionstatement. +As a result, each node in theturtlesim_world_2_launch.pylaunch description will have aturtlesim2namespace.4 Reusing nodesNow create abroadcaster_listener_launch.pyfile.fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([DeclareLaunchArgument('target_frame',default_value='turtle1',description='Target frame name.'),Node(package='turtle_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),Node(package='turtle_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster2',parameters=[{'turtlename':'turtle2'}]),Node(package='turtle_tf2_py',executable='turtle_tf2_listener',name='listener',parameters=[{'target_frame':LaunchConfiguration('target_frame')}]),])In this file, we have declared thetarget_framelaunch argument with a default value ofturtle1. +The default value means that the launch file can receive an argument to forward to its nodes, or in case the argument is not provided, it will pass the default value to its nodes.Afterwards, we use theturtle_tf2_broadcasternode two times using different names and parameters during launch. +This allows us to duplicate the same node without conflicts.We also start aturtle_tf2_listenernode and set itstarget_frameparameter that we declared and acquired above.5 Parameter overridesRecall that we called thebroadcaster_listener_launch.pyfile in our top-level launch file. +In addition to that, we have passed ittarget_framelaunch argument as shown below:broadcaster_listener_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/broadcaster_listener_launch.py']),launch_arguments={'target_frame':'carrot1'}.items(),)This syntax allows us to change the default goal target frame tocarrot1. +If you would liketurtle2to followturtle1instead of thecarrot1, just remove the line that defineslaunch_arguments. +This will assigntarget_frameits default value, which isturtle1.6 RemappingNow create amimic_launch.pyfile.fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtle2/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])])This launch file will start themimicnode, which will give commands to one turtlesim to follow the other. +The node is designed to receive the target pose on the topic/input/pose. +In our case, we want to remap the target pose from/turtle2/posetopic. +Finally, we remap the/output/cmd_veltopic to/turtlesim2/turtle1/cmd_vel. +This wayturtle1in ourturtlesim2simulation world will followturtle2in our initial turtlesim world.7 Config filesLet’s now create a file calledturtlesim_rviz_launch.py.importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():rviz_config=os.path.join(get_package_share_directory('turtle_tf2_py'),'rviz','turtle_rviz.rviz')returnLaunchDescription([Node(package='rviz2',executable='rviz2',name='rviz2',arguments=['-d',rviz_config])])This launch file will start the RViz with the configuration file defined in theturtle_tf2_pypackage. +This RViz configuration will set the world frame, enable TF visualization, and start RViz with a top-down view.8 Environment VariablesLet’s now create the last launch file calledfixed_broadcaster_launch.pyin our package.fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportEnvironmentVariable,LaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([DeclareLaunchArgument('node_prefix',default_value=[EnvironmentVariable('USER'),'_'],description='prefix for node name'),Node(package='turtle_tf2_py',executable='fixed_frame_tf2_broadcaster',name=[LaunchConfiguration('node_prefix'),'fixed_broadcaster'],),])This launch file shows the way environment variables can be called inside the launch files. +Environment variables can be used to define or push namespaces for distinguishing nodes on different computers or robots.NoteIf you are running the launch file where theUSERenvironment variable is not defined (like in the ROS docker file), then you can replace theEnvironmentVariable('USER')above with any other word of your liking.Running launch files1 Update setup.pyOpensetup.pyand add the following lines so that the launch files from thelaunch/folder and configuration file from theconfig/would be installed. +Thedata_filesfield should now look like this:importosfromglobimportglobfromsetuptoolsimportsetup...data_files=[...(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.[pxy][yma]*'))),(os.path.join('share',package_name,'config'),glob(os.path.join('config','*.yaml'))),(os.path.join('share',package_name,'rviz'),glob(os.path.join('config','*.rviz'))),],2 Build and runTo finally see the result of our code, build the package and launch the top-level launch file using the following command:ros2 launch launch_tutorial launch_turtlesim_launch.pyYou will now see the two turtlesim simulations started. +There are two turtles in the first one and one in the second one. +In the first simulation,turtle2is spawned in the bottom-left part of the world. +Its aim is to reach thecarrot1frame which is five meters away on the x-axis relative to theturtle1frame.Theturtlesim2/turtle1in the second is designed to mimic the behavior of theturtle2.If you want to control theturtle1, run the teleop node.ros2 run turtlesim turtle_teleop_keyAs a result, you will see a similar picture:In addition to that, the RViz should have started. +It will show all turtle frames relative to theworldframe, whose origin is at the bottom-left corner.SummaryIn this tutorial, you learned about various tips and practices of managing large projects using ROS 2 launch files. + +Code Examples: + +Language: unknown +importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcedefgenerate_launch_description():turtlesim_world_1=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_world_1_launch.py']))turtlesim_world_2=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_world_2_launch.py']))broadcaster_listener_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/broadcaster_listener_launch.py']),launch_arguments={'target_frame':'carrot1'}.items(),)mimic_node=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/mimic_launch.py']))fixed_frame_node=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/fixed_broadcaster_launch.py']))rviz_node=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_rviz_launch.py']))returnLaunchDescription([turtlesim_world_1,turtlesim_world_2,broadcaster_listener_nodes,mimic_node,fixed_frame_node,rviz_node]) + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfiguration,TextSubstitutionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():background_r_launch_arg=DeclareLaunchArgument('background_r',default_value=TextSubstitution(text='0'))background_g_launch_arg=DeclareLaunchArgument('background_g',default_value=TextSubstitution(text='84'))background_b_launch_arg=DeclareLaunchArgument('background_b',default_value=TextSubstitution(text='122'))returnLaunchDescription([background_r_launch_arg,background_g_launch_arg,background_b_launch_arg,Node(package='turtlesim',executable='turtlesim_node',name='sim',parameters=[{'background_r':LaunchConfiguration('background_r'),'background_g':LaunchConfiguration('background_g'),'background_b':LaunchConfiguration('background_b'),}]),]) + +Language: unknown +importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():config=os.path.join(get_package_share_directory('launch_tutorial'),'config','turtlesim.yaml')returnLaunchDescription([Node(package='turtlesim',executable='turtlesim_node',namespace='turtlesim2',name='sim',parameters=[config])]) + +Language: unknown +/turtlesim2/sim:ros__parameters:background_b:255background_g:86background_r:150 + +Language: unknown +...Node(package='turtlesim',executable='turtlesim_node',namespace='turtlesim3',name='sim',parameters=[config]) + +Language: unknown +/turtlesim3/sim:background_bbackground_gbackground_r + +Language: unknown +/**:ros__parameters:background_b:255background_g:86background_r:150 + +Language: unknown +namespace='turtlesim2', + +Language: unknown +fromlaunch.actionsimportGroupActionfromlaunch_ros.actionsimportPushROSNamespace...turtlesim_world_2=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/turtlesim_world_2_launch.py']))turtlesim_world_2_with_namespace=GroupAction(actions=[PushROSNamespace('turtlesim2'),turtlesim_world_2,]) + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([DeclareLaunchArgument('target_frame',default_value='turtle1',description='Target frame name.'),Node(package='turtle_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),Node(package='turtle_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster2',parameters=[{'turtlename':'turtle2'}]),Node(package='turtle_tf2_py',executable='turtle_tf2_listener',name='listener',parameters=[{'target_frame':LaunchConfiguration('target_frame')}]),]) + +Language: unknown +broadcaster_listener_nodes=IncludeLaunchDescription(PythonLaunchDescriptionSource([os.path.join(get_package_share_directory('launch_tutorial'),'launch'),'/broadcaster_listener_launch.py']),launch_arguments={'target_frame':'carrot1'}.items(),) + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtle2/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])]) + +Language: unknown +importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():rviz_config=os.path.join(get_package_share_directory('turtle_tf2_py'),'rviz','turtle_rviz.rviz')returnLaunchDescription([Node(package='rviz2',executable='rviz2',name='rviz2',arguments=['-d',rviz_config])]) + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportEnvironmentVariable,LaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([DeclareLaunchArgument('node_prefix',default_value=[EnvironmentVariable('USER'),'_'],description='prefix for node name'),Node(package='turtle_tf2_py',executable='fixed_frame_tf2_broadcaster',name=[LaunchConfiguration('node_prefix'),'fixed_broadcaster'],),]) + +Language: unknown +importosfromglobimportglobfromsetuptoolsimportsetup...data_files=[...(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.[pxy][yma]*'))),(os.path.join('share',package_name,'config'),glob(os.path.join('config','*.yaml'))),(os.path.join('share',package_name,'rviz'),glob(os.path.join('config','*.rviz'))),], + +Language: unknown +ros2 launch launch_tutorial launch_turtlesim_launch.py + +Language: unknown +ros2 run turtlesim turtle_teleop_key diff --git "a/exported_docs/ros2/Managing_nodes_with_managed_lifecycles\357\203\201.txt" "b/exported_docs/ros2/Managing_nodes_with_managed_lifecycles\357\203\201.txt" new file mode 100644 index 0000000..f8d29f8 --- /dev/null +++ "b/exported_docs/ros2/Managing_nodes_with_managed_lifecycles\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Managing nodes with managed lifecycles +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos/Managed-Nodes.html +Section: Installation +-------------------------------------------------------------------------------- + +Managing nodes with managed lifecyclesThis page lives now directly side-by-side with thecode. +For more information about thelifecyclepackage, refer torosindex. \ No newline at end of file diff --git "a/exported_docs/ros2/Marker:_Display_types\357\203\201.txt" "b/exported_docs/ros2/Marker:_Display_types\357\203\201.txt" new file mode 100644 index 0000000..4f0f42f --- /dev/null +++ "b/exported_docs/ros2/Marker:_Display_types\357\203\201.txt" @@ -0,0 +1,42 @@ +Title: Marker: Display types +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/RViz/Marker-Display-types/Marker-Display-types.html +Section: Installation +-------------------------------------------------------------------------------- + +Marker: Display typesGoal:This tutorial explains the basic Marker types and how to use them.Tutorial level:IntermediateTime:15 MinutesContentsBackgroundThe Marker Message1 Example Usage (C++)2 Message Parameters3 Object types4 Rendering Complexity NotesBackgroundThe Markers display allows programmatic addition of various primitive shapes to the 3D view by sending avisualization_msgs/msg/Markerorvisualization_msgs/msg/MarkerArraymessage.The Marker Message1 Example Usage (C++)First we will create a simple publisher node that publishesMarkermessages from thevisualization_messagespackage to thevisualization_markertopic:automarker_pub=node->create_publisher("visualization_marker",1);After that it is as simple as filling out avisualization_msgs/msg/Markermessage and publishing it:visualization_msgs::msg::Markermarker;marker.header.frame_id="/my_frame";marker.header.stamp=rclcpp::Clock().now();marker.ns="basic_shapes";marker.id=0;marker.type=visualization_msgs::msg::Marker::SPHERE;marker.action=visualization_msgs::msg::Marker::ADD;marker.pose.position.x=0;marker.pose.position.y=0;marker.pose.position.z=0;marker.pose.orientation.x=0.0;marker.pose.orientation.y=0.0;marker.pose.orientation.z=0.0;marker.pose.orientation.w=1.0;marker.scale.x=1.0;marker.scale.y=1.0;marker.scale.z=1.0;marker.color.r=0.0f;marker.color.g=1.0f;marker.color.b=0.0f;marker.color.a=1.0;// Don't forget to set the alpha!// only if using a MESH_RESOURCE marker type:marker.mesh_resource="package://pr2_description/meshes/base_v0/base.dae";marker.lifetime=rclcpp::Duration::from_nanoseconds(0);marker_pub->publish(marker);There is also avisualization_msgs/msg/MarkerArraymessage, which lets you publish many markers at once.2 Message ParametersThe Marker message type is defined inROS2CommonInterfaces_package. +The messages in this package include comments that are helpful in understanding each of the fields in the message.ns:Namespace for these markers. This plus the id form a unique identifier.id:Unique id assigned to this marker. It is your responsibility to keep these unique within your namespace.type:Type of marker (Arrow, Sphere, …). The available types are specified in the message definition.action:0 = add/modify, 1 = (deprecated), 2 = delete, 3 = deleteallpose:Pose marker, specified as x/y/z position and x/y/z/w quaternion orientation.scale:Scale of the marker. Applied before the position/orientation. A scale of [1, 1, 1] means the object will be 1m by 1m by 1m.color:Color of the object, specified as r/g/b/a, with values in the range of [0, 1]. The,aor alpha value, denotes the opacity of the marker with 1 indicating opaque and 0 indicating completely transparent. The default value is 0, or completely transparent.You must set the a value of your marker to a non-zero value or it will be transparent by default!points:Only used for markers of typePoints,Linestrips, andLine/Cube/Sphere-lists. +It’s also used for the Arrow type, if you want to specify the arrow start and end points. +This entry represents a list ofgeometry_msgs/Pointtypes for the center or each marker object you would like rendered.colors:This field is only used for markers that use the points member. This field specifies per-vertex color r/g/b/ color (no alpha yet) for each entry inpoints.lifetime:Aduration message valueused to automatically delete the marker after this period of time. +The countdown resets if another marker of the samenamespace/idis received.frame_locked:Without theframe_lockedparameter the marker will be placed based on the current transform and will stay there even if the given transform changes later. +Setting this parameter tells RViz to retransform the marker to the new current location of the specified frame on every update cycle.text:The text string used for theTEXT_VIEW_FACINGmarker typemesh_resource:The resource location for theMESH_RESOURCEmarker type. Can be any mesh type supported by RViz (.stlor Ogre.meshin 1.0, with the addition of COLLADA in 1.1). +The format is the URI-form used byresource_retriever, including the package:// syntax.3 Object types3.1 Arrow (ARROW=0)The arrow type provides two different ways of specifying where the arrow should begin/end:Position/Orientation:Pivot point is around the tip of its tail. Identity orientation points it along the +X axis.scale.xis the arrow length,scale.yis the arrow width andscale.zis the arrow height.Start/EndPoints:You can also specify a start/end point for the arrow, using the points member. If you put points into the points member, it will assume you want to do things this way.The point at index 0 is assumed to be the start point, and the point at index 1 is assumed to be the end.scale.xis the shaft diameter, andscale.yis the head diameter. Ifscale.zis not zero, it specifies the head length.3.2 Cube (CUBE=1)Pivot point is at the center of the cube.3.3 Sphere (SPHERE=2)Pivot point is at the center of the sphere.scale.xis diameter in x direction,scale.yin y direction,scale.zin z direction. +By setting these to different values you get an ellipsoid instead of a sphere.3.4 Cylinder (CYLINDER=3)Pivot point is at the center of the cylinder.scale.xis diameter in x direction,scale.yin y direction, by setting these to different values you get an ellipse instead of a circle. +Usescale.zto specify the height.3.5 Line Strip (LINE_STRIP=4)Line strips use the points member of thevisualization_msgs/msg/Markermessage. +It will draw a line between every two consecutive points, so 0-1, 1-2, 2-3, 3-4, 4-5…Line strips also have some special handling for scale: onlyscale.xis used and it controls the width of the line segments.Note thatposeis still used (the points in the line will be transformed by them), and the lines will be correct relative to theframeidspecified in the header.3.6 Line List (LINE_LIST=5)Line lists use the points member of thevisualization_msgs/msg/Markermessage. It will draw a line between each pair of points, so 0-1, 2-3, 4-5, …Line lists also have some special handling for scale: onlyscale.xis used and it controls the width of the line segments.Note thatposeis still used (the points in the line will be transformed by them), and the lines will be correct relative to theframeidspecified in the header.3.7 Cube List (CUBE_LIST=6)A cube list is a list of cubes with all the same properties except their positions. +Using this object type instead of avisualization_msgs/msg/MarkerArrayallows RViz to batch-up rendering, +which causes them to render much faster. +The caveat is that they all must have the same scale.Thepointsmember of thevisualization_msgs/msg/Markermessage is used for the position of each cube.3.8 Sphere List (SPHERE_LIST=7)A sphere list is a list of spheres with all the same properties except their positions. +Using this object type instead of avisualization_msgs/msg/MarkerArrayallows RViz to batch-up rendering, +which causes them to render much faster. +The caveat is that they all must have the same scale.Thepointsmember of thevisualization_msgs/msg/Markermessage is used for the position of each sphere.Note thatposeis still used (thepointsin the line will be transformed by them), and the lines will be correct relative to theframeidspecified in the header.3.9 Points (POINTS=8)Uses thepointsmember of thevisualization_msgs/msg/Markermessage.Pointshave some special handling for scale:scale.xis point width,scale.yis point heightNote thatposeis still used (thepointsin the line will be transformed by them), and the lines will be correct relative to theframeidspecified in the header.3.10 View-Oriented Text (TEXT_VIEW_FACING=9)This marker displays text in a 3D spot in the world. +The text always appears oriented correctly for the RViZ user to see the included text. Uses thetextfield in the marker.Onlyscale.zis used.scale.zspecifies the height of an uppercase “A”.3.11 Mesh Resource (MESH_RESOURCE=10)Uses themesh_resourcefield in the marker. +Can be any mesh type supported by RViz (binary.stlor Ogre.meshin 1.0, with the addition of COLLADA (.dae) in 1.1). +The format is the URI-form used byresource_retriever, including thepackage://syntax.An example of a mesh an its use is:marker.type=visualization_msgs::Marker::MESH_RESOURCE;marker.mesh_resource="package://pr2_description/meshes/base_v0/base.dae";Scale on a mesh is relative. +A scale of (1.0, 1.0, 1.0) means the mesh will display as the exact size specified in the mesh file. +A scale of (1.0, 1.0, 2.0) means the mesh will show up twice as tall, but the same width/depth.If themesh_use_embedded_materialsflag is set to true and the mesh is of a type which supports embedded materials (such as COLLADA), +the material defined in that file will be used instead of the color defined in the marker.Since version [1.8], even whenmesh_use_embedded_materialsis true, +if the markercoloris set to anything other thanr=0,g=0,b=0,a=0the markercolorandalphawill be used to tint the mesh with the embedded material.3.12 Triangle List (TRIANGLE_LIST=11)Uses the points and optionally colors members. +Every set of 3 points is treated as a triangle, so indices 0-1-2, 3-4-5, etc.Note thatposeandscaleare still used (the points in the line will be transformed by them), +and the lines will be correct relative to theframeidspecified in the header.4 Rendering Complexity NotesA single marker is always less expensive to render than many markers. +For example, a single cube list can handle thousands of cubes, where we will not be able to render thousands of individual cube markers. + +Code Examples: + +Language: unknown +automarker_pub=node->create_publisher("visualization_marker",1); + +Language: unknown +visualization_msgs::msg::Markermarker;marker.header.frame_id="/my_frame";marker.header.stamp=rclcpp::Clock().now();marker.ns="basic_shapes";marker.id=0;marker.type=visualization_msgs::msg::Marker::SPHERE;marker.action=visualization_msgs::msg::Marker::ADD;marker.pose.position.x=0;marker.pose.position.y=0;marker.pose.position.z=0;marker.pose.orientation.x=0.0;marker.pose.orientation.y=0.0;marker.pose.orientation.z=0.0;marker.pose.orientation.w=1.0;marker.scale.x=1.0;marker.scale.y=1.0;marker.scale.z=1.0;marker.color.r=0.0f;marker.color.g=1.0f;marker.color.b=0.0f;marker.color.a=1.0;// Don't forget to set the alpha!// only if using a MESH_RESOURCE marker type:marker.mesh_resource="package://pr2_description/meshes/base_v0/base.dae";marker.lifetime=rclcpp::Duration::from_nanoseconds(0);marker_pub->publish(marker); + +Language: unknown +marker.type=visualization_msgs::Marker::MESH_RESOURCE;marker.mesh_resource="package://pr2_description/meshes/base_v0/base.dae"; diff --git "a/exported_docs/ros2/Marketing\357\203\201.txt" "b/exported_docs/ros2/Marketing\357\203\201.txt" new file mode 100644 index 0000000..4f03fe1 --- /dev/null +++ "b/exported_docs/ros2/Marketing\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: Marketing +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Marketing.html +Section: Installation +-------------------------------------------------------------------------------- + +MarketingGeneral Use ROS ArtworkThe ROS 2 media kit, which includes branding language, high resolution ROS logo +graphics, and release images, can be found in theROS art +repository.Please refer to +this repository for ROS art work and our branding guidelines.Stickers, Posters, and Canvas PrintsOpen Robotics hosts an online storefront onZazzle.comwith artwork available in various formats.PostersPrinted on paper with selectable sizes.Canvas PrintsPrinted on wrapped canvas with selectable sizes.Sticker SheetsPrinted on a sheet, 20 per sheet for the small, 6 per sheet in the large size.Brochure: Why ROS 2?Use this brochure to promote the goals and features of ROS 2 and encourage adoption.License:CC BY-ND 4.0Available formats:A4(forweb/email)A4(forprint)USLetter(forweb/email)USLetter(forprint) \ No newline at end of file diff --git "a/exported_docs/ros2/Metrics\357\203\201.txt" "b/exported_docs/ros2/Metrics\357\203\201.txt" new file mode 100644 index 0000000..1dae870 --- /dev/null +++ "b/exported_docs/ros2/Metrics\357\203\201.txt" @@ -0,0 +1,10 @@ +Title: Metrics +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Metrics.html +Section: Installation +-------------------------------------------------------------------------------- + +MetricsTable of ContentsMetrics.ros.orgPeriodic Metrics ReportHistorical Metrics ReportsWe measure aspects of the ROS community to understand and track the impact of our work and identify areas for improvement. +We take inspiration from the MeeGo Project’s metrics.Metrics.ros.orgAtmetrics.ros.orgyou can find many visualizations of metrics about ROS.Periodic Metrics ReportWe periodically publish a metrics report that provides a quantitative view of the ROS community. +We’re collectively learning what to measure and how and evoloving as systems change. +Please provide feedback! +Add your suggestions on how to improve these reports by posting them toROS Discourse Site Feedback Category.Historical Metrics Reports2023202220212020201920182017201620152014201320122011 \ No newline at end of file diff --git "a/exported_docs/ros2/Migrating_C++_Packages_Reference\357\203\201.txt" "b/exported_docs/ros2/Migrating_C++_Packages_Reference\357\203\201.txt" new file mode 100644 index 0000000..a6a3fbd --- /dev/null +++ "b/exported_docs/ros2/Migrating_C++_Packages_Reference\357\203\201.txt" @@ -0,0 +1,147 @@ +Title: Migrating C++ Packages Reference +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating C++ Packages ReferenceTable of ContentsBuild toolUpdate yourCMakeLists.txtto useament_cmakeRequire a newer version of CMakeSet the build type to ament_cmakeAdd a call toament_package()Updatefind_package()callsUse modern CMake targetsReplacecatkin_package()with various ament_cmake callsGenerate messagesRemove references to the devel spaceUnit testsLintersUpdate source codeMessages, services, and actionsUse of service objectsUsages of ros::TimeUsages of ros::RateBoostThis page shows how to migrate parts of a C++ package from ROS 1 to ROS 2. +If this is your first time migrating a C++ package, then read theC++ migration examplefirst. +Afterwards, use this page as a reference while you migrate your own packages.Build toolInstead of usingcatkin_make,catkin_make_isolatedorcatkinbuildROS 2 uses the command line toolcolconto build and install a set of packages. +See thebeginner tutorialto get started withcolcon.Update yourCMakeLists.txtto useament_cmakeROS 2 C++ packages useCMakewith convenience functions provided byament_cmake. +Apply the following changes to useament_cmakeinstead ofcatkin.Require a newer version of CMakeROS 2 relies on newer versions of CMake than used by ROS 1. +Find the minimum version of CMake used by the ROS distribution you want to support inREP 2000, and use that version at the top of yourCMakeLists.txt. +For example,3.14.4 is the minimum recommended support for ROS Humble.cmake_minimum_required(VERSION3.14.4)Set the build type to ament_cmakeRemove any dependencies oncatkinfrom yourpackage.xml# Remove this!catkinAdd a new dependency onament_cmake_ros(example):ament_cmake_rosAdd ansection to yourpackage.xmlif it does not have one already. +Set thetoament_cmake(example)ament_cmakeAdd a call toament_package()Insert a call toament_package()at the bottom of yourCMakeLists.txt(example)# Add this to the bottom of your CMakeLists.txtament_package()Updatefind_package()callsReplace thefind_package(catkinCOMPONENTS...)call with individualfind_package()calls (example):For example, change this:find_package(catkinREQUIREDCOMPONENTSfoobarstd_msgs)find_package(bazREQUIRED)To this:find_package(ament_cmake_rosREQUIRED)find_package(fooREQUIRED)find_package(barREQUIRED)find_package(std_msgsREQUIRED)find_package(bazREQUIRED)Use modern CMake targetsPrefer to use per-target CMake functions so that your package can export modern CMake targets.If yourCMakeLists.txtusesinclude_directories(), then delete those calls.# Delete calls to include_directories like this one! +include_directories(include ${catkin_INCLUDE_DIRS})Add a calltarget_include_directories()for every library in your pacakage (example).target_include_directories(my_libraryPUBLIC"$""$")Change alltarget_link_libraries()calls to use modern CMake targets. +For example, if your package in ROS 1 uses old-style standard CMake variables like this.target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES})Then change it to use specific modern CMake targets instead. +Use${package_name_TARGETS}if the package you’re depending on is a message package such asstd_msgs.target_link_libraries(my_libraryPUBLICfoo::foobar::bar${std_msgs_TARGETS}baz::baz)ChoosePUBLICorPRIVATEbased on how the dependency is used by your library (example).UsePUBLICif the dependency is needed by downstream users, for example, your library’s public API uses it.UsePRIVATEif the dependency is only used internally by your library.Replacecatkin_package()with various ament_cmake callsImagine yourCMakeLists.txthas a call tocatkin_packagelike this:catkin_package( + INCLUDE_DIRS include + LIBRARIES my_library + CATKIN_DEPENDS foo bar std_msgs + DEPENDS baz +) + +install(TARGETS my_library + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} +)Replacingcatkin_package(INCLUDE_DIRS...)If you’ve used modern CMake targets andtarget_include_directories(), you don’t need to do anything further. +Downstream users will get the include directories by depending on your modern CMake targets.Replacingcatkin_package(LIBRARIES...)Useament_export_targets()andinstall(TARGETS...EXPORT...)to replace theLIBRARIESargument.Use theEXPORTkeyword when installing yourmy_librarytarget (example).install(TARGETSmy_libraryEXPORTexport_my_packageARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)The above is a good default for library targets. +If your package used differentCATKIN_*_DESTINATIONvariables, convert them as follows:catkinament_cmakeCATKIN_GLOBAL_BIN_DESTINATIONbinCATKIN_GLOBAL_INCLUDE_DESTINATIONincludeCATKIN_GLOBAL_LIB_DESTINATIONlibCATKIN_GLOBAL_LIBEXEC_DESTINATIONlibCATKIN_GLOBAL_SHARE_DESTINATIONshareCATKIN_PACKAGE_BIN_DESTINATIONlib/${PROJECT_NAME}CATKIN_PACKAGE_INCLUDE_DESTINATIONinclude/${PROJECT_NAME}CATKIN_PACKAGE_LIB_DESTINATIONlibCATKIN_PACKAGE_SHARE_DESTINATIONshare/${PROJECT_NAME}Add a call toament_export_targets()with the same name you gave to theEXPORTkeyword (example).ament_export_targets(export_my_package)Replacingcatkin_package(CATKIN_DEPENDS..DEPENDS..)Your package’s users mustfind_package()dependencies used by your package’s public API. +In ROS 1 this was done for downstream users with theCATKIN_DEPENDSandDEPENDSarguments. +Useament_export_dependenciesto do this in ROS 2.ament_export_dependencies(foobarstd_msgsbaz)Generate messagesIf your package contains both C++ code and ROS message, service, or action definitions, then consider splitting it into two packages:A package with only the ROS message, service, and/or action definitionsA package with the C++ codeAdd the following dependencies to thepackage.xmlof the package that contains ROS messages:Add aonrosidl_default_generators(example)rosidl_default_generatorsAdd anonrosidl_default_runtime(example)rosidl_default_runtimeAdd atag with the group namerosidl_interface_packages(example)rosidl_interface_packagesIn yourCMakeLists.txt, replace the invocation ofadd_message_files,add_service_filesandgenerate_messageswithrosidl_generate_interfaces. +The first argument must be${PROJECT_NAME}due tothis bug.For example, if your ROS 1 package looks like this:add_message_files(DIRECTORYmsgFILESFooBar.msgBaz.msg)add_service_files(DIRECTORYsrvFILESPing.srv)add_action_files(DIRECTORYactionFILESDoPong.action)generate_messages(DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs)Then change it to this (example)rosidl_generate_interfaces(${PROJECT_NAME}"msg/FooBar.msg""msg/Baz.msg""srv/Ping.srv""action/DoPong.action"DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs)Remove references to the devel spaceRemove any references to thedevel spacesuch asCATKIN_DEVEL_PREFIX. +There is no equivalent to thedevel spacein ROS 2.Unit testsIf your package usesgtestthen:ReplaceCATKIN_ENABLE_TESTINGwithBUILD_TESTING.Replacecatkin_add_gtestwithament_add_gtest.Add afind_package()forament_cmake_gtestinstead ofGTestFor example, if your ROS 1 package adds tests like this:if (CATKIN_ENABLE_TESTING) + find_package(GTest REQUIRED) + include_directories(${GTEST_INCLUDE_DIRS}) + catkin_add_gtest(my_test src/test/some_test.cpp) + target_link_libraries(my_test + # ... + ${GTEST_LIBRARIES}) +endif()Then change it to this:if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(my_testsrc/test/test_something.cpp)target_link_libraries(my_test#...)endif()Addament_cmake_gtestto yourpackage.xml(example).ament_cmake_gtestLintersThe ROS 2 codestyle guidediffers from ROS 1.If you choose to follow the ROS 2 style guide, then turn on automatic linter tests by adding these lines in aif(BUILD_TESTING)block:if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()# ...endif()Add the following dependencies to yourpackage.xml:ament_lint_autoament_lint_commonUpdate source codeMessages, services, and actionsThe namespace of ROS 2 messages, services, and actions use a subnamespace (msg,srv, oraction, respectively) after the package name. +Therefore an include looks like:#include. +The C++ type is then named:my_interfaces::msg::MyMessage.Shared pointer types are provided as typedefs within the message structs:my_interfaces::msg::MyMessage::SharedPtras well asmy_interfaces::msg::MyMessage::ConstSharedPtr.For more details please see the article about thegenerated C++ interfaces.The migration requires includes to change by:inserting the subfoldermsgbetween the package name and message datatypechanging the included filename from CamelCase to underscore separationchanging from*.hto*.hpp// ROS 1 style is in comments, ROS 2 follows, uncommented.// # include #include// geometry_msgs::PointStamped point_stamped;geometry_msgs::msg::PointStampedpoint_stamped;The migration requires code to insert themsgnamespace into all instances.Use of service objectsService callbacks in ROS 2 do not have boolean return values. +Instead of returning false on failures, throwing exceptions is recommended.// ROS 1 style is in comments, ROS 2 follows, uncommented.// #include "nav_msgs/GetMap.h"#include"nav_msgs/srv/get_map.hpp"// bool service_callback(// nav_msgs::GetMap::Request & request,// nav_msgs::GetMap::Response & response)voidservice_callback(conststd::shared_ptrrequest,std::shared_ptrresponse){// ...// return true; // or false for failure}Usages of ros::TimeFor usages ofros::Time:Replace all instances ofros::Timewithrclcpp::TimeIf your messages or code makes use of std_msgs::Time:Convert all instances of std_msgs::Time to builtin_interfaces::msg::TimeConvert all#include"std_msgs/time.hto#include"builtin_interfaces/msg/time.hpp"Convert all instances using the std_msgs::Time fieldnsecto the builtin_interfaces::msg::Time fieldnanosecUsages of ros::RateThere is an equivalent typerclcpp::Rateobject which is basically a drop in replacement forros::Rate.BoostMuch of the functionality previously provided by Boost has been integrated into the C++ standard library. +As such we would like to take advantage of the new core features and avoid the dependency on boost where possible.Shared PointersTo switch shared pointers from boost to standard C++ replace instances of:#includewith#includeboost::shared_ptrwithstd::shared_ptrThere may also be variants such asweak_ptrwhich you want to convert as well.Also it is recommended practice to useusinginstead oftypedef.usinghas the ability to work better in templated logic. +For detailssee hereThread/MutexesAnother common part of boost used in ROS codebases are mutexes inboost::thread.Replaceboost::mutex::scoped_lockwithstd::unique_lockReplaceboost::mutexwithstd::mutexReplace#includewith#includeUnordered MapReplace:#includewith#includeboost::unordered_mapwithstd::unordered_mapfunctionReplace:#includewith#includeboost::functionwithstd::function + +Code Examples: + +Language: unknown +cmake_minimum_required(VERSION3.14.4) + +Language: unknown +# Remove this!catkin + +Language: unknown +ament_cmake_ros + +Language: unknown +ament_cmake + +Language: unknown +# Add this to the bottom of your CMakeLists.txtament_package() + +Language: unknown +find_package(catkinREQUIREDCOMPONENTSfoobarstd_msgs)find_package(bazREQUIRED) + +Language: unknown +find_package(ament_cmake_rosREQUIRED)find_package(fooREQUIRED)find_package(barREQUIRED)find_package(std_msgsREQUIRED)find_package(bazREQUIRED) + +Language: unknown +# Delete calls to include_directories like this one! +include_directories(include ${catkin_INCLUDE_DIRS}) + +Language: unknown +target_include_directories(my_libraryPUBLIC"$""$") + +Language: unknown +target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES}) + +Language: unknown +target_link_libraries(my_libraryPUBLICfoo::foobar::bar${std_msgs_TARGETS}baz::baz) + +Language: unknown +catkin_package( + INCLUDE_DIRS include + LIBRARIES my_library + CATKIN_DEPENDS foo bar std_msgs + DEPENDS baz +) + +install(TARGETS my_library + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} +) + +Language: unknown +install(TARGETSmy_libraryEXPORTexport_my_packageARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin) + +Language: unknown +ament_export_targets(export_my_package) + +Language: unknown +ament_export_dependencies(foobarstd_msgsbaz) + +Language: unknown +rosidl_default_generators + +Language: unknown +rosidl_default_runtime + +Language: unknown +rosidl_interface_packages + +Language: unknown +add_message_files(DIRECTORYmsgFILESFooBar.msgBaz.msg)add_service_files(DIRECTORYsrvFILESPing.srv)add_action_files(DIRECTORYactionFILESDoPong.action)generate_messages(DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs) + +Language: unknown +rosidl_generate_interfaces(${PROJECT_NAME}"msg/FooBar.msg""msg/Baz.msg""srv/Ping.srv""action/DoPong.action"DEPENDENCIESactionlib_msgsstd_msgsgeometry_msgs) + +Language: unknown +if (CATKIN_ENABLE_TESTING) + find_package(GTest REQUIRED) + include_directories(${GTEST_INCLUDE_DIRS}) + catkin_add_gtest(my_test src/test/some_test.cpp) + target_link_libraries(my_test + # ... + ${GTEST_LIBRARIES}) +endif() + +Language: unknown +if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(my_testsrc/test/test_something.cpp)target_link_libraries(my_test#...)endif() + +Language: unknown +ament_cmake_gtest + +Language: unknown +if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()# ...endif() + +Language: unknown +ament_lint_autoament_lint_common + +Language: unknown +// ROS 1 style is in comments, ROS 2 follows, uncommented.// # include #include// geometry_msgs::PointStamped point_stamped;geometry_msgs::msg::PointStampedpoint_stamped; + +Language: unknown +// ROS 1 style is in comments, ROS 2 follows, uncommented.// #include "nav_msgs/GetMap.h"#include"nav_msgs/srv/get_map.hpp"// bool service_callback(// nav_msgs::GetMap::Request & request,// nav_msgs::GetMap::Response & response)voidservice_callback(conststd::shared_ptrrequest,std::shared_ptrresponse){// ...// return true; // or false for failure} diff --git "a/exported_docs/ros2/Migrating_Interfaces\357\203\201.txt" "b/exported_docs/ros2/Migrating_Interfaces\357\203\201.txt" new file mode 100644 index 0000000..9b47a55 --- /dev/null +++ "b/exported_docs/ros2/Migrating_Interfaces\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: Migrating Interfaces +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Interfaces.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating InterfacesTable of ContentsInterface definitionsBuilding interfacesMigrating interface package to ROS 2Messages, services, and actions are collectively calledinterfacesin ROS 2.Interface definitionsMessage files must end in.msgand must be located in the subfoldermsg. +Service files must end in.srvand must be located in the subfoldersrv. +Actions files must end in.actionand must be located in the subfolderaction.These files might need to be updated to comply with theROS Interface definition. +Some primitive types have been removed and the typesdurationandtimewhich were builtin types in ROS 1 have been replaced with normal message definitions and must be used from thebuiltin_interfacespackage. +Also some naming conventions are stricter than in ROS 1. +There is additional information in theconceptual article.Building interfacesThe way in which interfaces are built in ROS 2 differs substantially from ROS 1. +Interfaces can only be built from packages containing aCMakeLists.txt. +If you are developing a pure Python package, then the interfaces should be placed in a different package containing only the interfaces (which is best practice anyway). +See thecustom interfaces tutorialfor more information.Migrating interface package to ROS 2In yourpackage.xml:Addrosidl_default_generators.Addrosidl_default_runtime.Addrosidl_interface_packagesFor each dependent message package, addmessage_package.In yourCMakeLists.txt:Enable C++17set(CMAKE_CXX_STANDARD17)Addfind_package(rosidl_default_generatorsREQUIRED)For each dependent message package, addfind_package(message_packageREQUIRED)and replace the CMake function call togenerate_messageswithrosidl_generate_interfaces.This will replaceadd_message_filesandadd_service_fileslisting of all the message and service files, which can be removed. + +Code Examples: + +Language: unknown +set(CMAKE_CXX_STANDARD17) diff --git "a/exported_docs/ros2/Migrating_Launch_Files\357\203\201.txt" "b/exported_docs/ros2/Migrating_Launch_Files\357\203\201.txt" new file mode 100644 index 0000000..ef3ee65 --- /dev/null +++ "b/exported_docs/ros2/Migrating_Launch_Files\357\203\201.txt" @@ -0,0 +1,80 @@ +Title: Migrating Launch Files +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Launch-Files.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating Launch FilesTable of ContentsBackgroundMigrating tagsNew tags in ROS 2Replacing an include tagSubstitutionsType inference rulesWhile launch files in ROS 1 are always specified using.xmlfiles, ROS 2 supports Python scripts to enable more flexibility (seelaunch package) as well as XML and YAML files.This guide describes how to write ROS 2 XML launch files for an easy migration from ROS 1.BackgroundA description of the ROS 2 launch system and its Python API can be found inLaunch System tutorial.Migrating tagslaunchAvailable in ROS 1.launchis the root element of any ROS 2 launch XML file.nodeAvailable in ROS 1.Launches a new node.Differences from ROS 1:typeattribute is nowexec.nsattribute is nownamespace.The following attributes aren’t available:machine,respawn_delay,clear_params.ExampleparamAvailable in ROS 1.Used for passing a parameter to a node.There’s no global parameter concept in ROS 2. +For that reason, it can only be used nested in anodetag. +Some attributes aren’t supported in ROS 2:type,textfile,binfile,executable.Thecommandattribute is nowvalue="$(command'...')".ExampleType inference rulesHere are some examples of how to write parameters:Parameter groupingIn ROS 2,paramtags are allowed to be nested. +For example:That will create two parameters:Agroup1.group2.my_paramof value1, hosted by node/an_absolute_ns/my_node.Agroup1.another_paramof value2hosted by node/an_absolute_ns/my_node.It’s also possible to use full parameter names:rosparamAvailable in ROS 1.Loads parameters from a yaml file.It has been replaced with afromattribute inparamtags.ExampleremapAvailable in ROS 1.Used to pass remapping rules to a node.It can only be used withinnodetags.ExampleincludeAvailable in ROS 1.Allows including another launch file.Differences from ROS 1:Available in ROS 1, included content was scoped. +In ROS 2, it’s not. +Nest includes ingrouptags to scope them.nsattribute is not supported. +See example ofpush_ros_namespacetag for a workaround.argtags nested in anincludetag don’t support conditionals (if,unless) or thedescriptionattribute.There is no support for nestedenvtags.set_envandunset_envcan be used instead.Bothclear_paramsandpass_all_argsattributes aren’t supported.ExamplesSeeReplacing an include tag.argAvailable in ROS 1.argis used for declaring a launch argument, or to pass an argument when usingincludetags.Differences from ROS 1:valueattribute is not allowed. +Uselettag for this.docis nowdescription.When nested within anincludetag,if,unless, anddescriptionattributes aren’t allowed.ExamplePassing an argument to the launch fileIn the XML launch file above, thetopic_namedefaults to the namechatter, but can be configured on the command-line. +Assuming the above launch configuration is in a file namedmylaunch.xml, a different topic name can be used by launching it with the following:ros2launchmylaunch.xmltopic_name:=custom_topic_nameThere is some additional information about passing command-line arguments inUsing Substitutions.envAvailable in ROS 1.Sets an environment variable.It has been replaced withenv,set_envandunset_env:envcan only be used nested in anodeorexecutabletag.ifandunlesstags aren’t supported.set_envcan be nested within the root taglaunchor ingrouptags. +It accepts the same attributes asenv, and alsoifandunlesstags.unset_envunsets an environment variable. +It accepts anameattribute and conditionals.ExamplegroupAvailable in ROS 1.Allows limiting the scope of launch configurations. +Usually used together withlet,includeandpush_ros_namespacetags.Differences from ROS 1:There is nonsattribute. +See the newpush_ros_namespacetag as a workaround.clear_paramsattribute isn’t available.It doesn’t acceptremapnorparamtags as children.Examplelaunch-prefixconfiguration affects bothexecutableandnodetags’ actions. +This example will usetimeas a prefix ifuse_time_prefix_in_talkerargument is1, only for the talker.machineIt is not supported at the moment.testIt is not supported at the moment.New tags in ROS 2set_env and unset_envSeeenvtag decription.push_ros_namespaceincludeandgrouptags don’t accept annsattribute. +This action can be used as a workaround:letIt’s a replacement ofargtag with a value attribute.executableIt allows running any executable.ExampleReplacing an include tagIn order to include a launch file under anamespaceas in ROS 1 then theincludetags must be nested in agrouptag.Then, instead of using thensattribute, add thepush_ros_namespaceaction tag to specify the namespace:Nestingincludetags under agrouptag is only required when specifying a namespaceSubstitutionsDocumentation about ROS 1’s substitutions can be found inroslaunch XML wiki. +Substitutions syntax hasn’t changed, i.e. it still follows the$(substitution-namearg1arg2...)pattern. +There are, however, some changes w.r.t. ROS 1:envandoptenvtags have been replaced by theenvtag.$(env)will fail if the environment variable doesn’t exist.$(env'')does the same as ROS 1’s$(optenv).$(env)does the same as ROS 1’s$(env)or$(optenv).findhas been replaced withfind-pkg-share(substituting the share directory of an installed package). +Alternativelyfind-pkg-prefixwill return the root of an installed package.There is a newexec-in-pkgsubstitution. +e.g.:$(exec-in-pkg).There is a newfind-execsubstitution.arghas been replaced withvar. +It looks at configurations defined either withargorlettag.evalanddirnamesubstitutions require escape characters for string values, e.g.if="$(eval'\'$(varvariable)\'==\'val1\'')".anonsubstitution is not supported.Type inference rulesThe rules that were shown inTypeinferencerulessubsection ofparamtag applies to any attribute. +For example:Some attributes accept more than a single type, for examplevalueattribute ofparamtag. +It’s usual that parameters that are of typeint(orfloat) also accept anstr, that will be later substituted and tried to convert to anint(orfloat) by the action. + +Code Examples: + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown +ros2launchmylaunch.xmltopic_name:=custom_topic_name + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown + diff --git "a/exported_docs/ros2/Migrating_Packages\357\203\201.txt" "b/exported_docs/ros2/Migrating_Packages\357\203\201.txt" new file mode 100644 index 0000000..44b243e --- /dev/null +++ "b/exported_docs/ros2/Migrating_Packages\357\203\201.txt" @@ -0,0 +1,16 @@ +Title: Migrating Packages +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Packages.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating PackagesTable of ContentsPrerequisitesPackage.xml format versionDependency namesMetapackagesLicensingChanging the LicenseThere are two different kinds of package migrations:Migrating the source code of an existing package from ROS 1 to ROS 2 with the intent that a significant part of the source code will stay the same or at least similar. +An example for this ispluginlibwhere the source code is maintained in different branches within the same repository and common patches can be ported between those branches when necessary.Implementing the same or similar functionality of a ROS 1 package for ROS 2 but with the assumption that the source code will be significantly different. +An example for this isroscppin ROS 1 andrclcppin ROS 2 which are separate repositories and don’t share any code.PrerequisitesBefore being able to migrate a ROS 1 package to ROS 2 all of its dependencies must be available in ROS 2.Package.xml format versionROS 2 only supportspackage.xmlformat versions 2 and higher. +If your package’spackage.xmluses format 1, then update it using thePackage.xml format 1 to 2 migration guide.Dependency namesDependency names that come fromrosdepshould not need to change, as those are shared across ROS 1 and ROS 2.Some packages released into ROS might have different names in ROS 2 so the dependencies might need to be updated accordingly.MetapackagesROS 2 doesn’t have a special package type for metapackages. +Metapackages can still exist as regular packages that only contain runtime dependencies. +When migrating metapackages from ROS 1, simply remove thetag in your package manifest. +SeeUsing variantsfor more information on metapackages/variants.LicensingIn ROS 1 our recommended license was the3-Clause BSD License. +In ROS 2 our recommended license is theApache 2.0 License.For any new project we recommend using the Apache 2.0 License, whether ROS 1 or ROS 2.However, when migrating code from ROS 1 to ROS 2 we cannot simply change the license. +The existing license must be preserved for any preexisting contributions.To that end if a package is being migrated we recommend keeping the existing license and continuing to contribute to that package under the existing OSI license, which we expect to be the BSD license for core elements.This will keep things clear and easy to understand.Changing the LicenseIt is possible to change the license, however you will need to contact all the contributors and get permission. +For most packages this is likely to be a significant effort and not worth considering. +If the package has a small set of contributors then this may be feasible. \ No newline at end of file diff --git "a/exported_docs/ros2/Migrating_Parameters\357\203\201.txt" "b/exported_docs/ros2/Migrating_Parameters\357\203\201.txt" new file mode 100644 index 0000000..90aa6e9 --- /dev/null +++ "b/exported_docs/ros2/Migrating_Parameters\357\203\201.txt" @@ -0,0 +1,17 @@ +Title: Migrating Parameters +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Parameters.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating ParametersTable of ContentsMigrating YAML Parameter FilesYAML file exampleFeature parityIn ROS 1, parameters are associated with a central server that allowed retrieving parameters at runtime through the use of the network APIs. +In ROS 2, parameters are associated per node and are configurable at runtime with ROS services.SeeROS 2 Parameter design documentfor more details about the system model.SeeROS 2 CLI usagefor a better understanding of how the CLI tools work and its differences with ROS 1 tooling.Migrating YAML Parameter FilesThis guide describes how to adapt ROS 1 parameters files for ROS 2.YAML file exampleYAML is used to write parameters files in both ROS 1 and ROS 2. +The main difference in ROS 2 is that node names must be used to address parameters. +In addition to the fully qualified node name, we use the key “ros__parameters” to signal the start of parameters for the node.For example, here is a parameters file in ROS 1:lidar_name:foolidar_id:10ports:[11312,11311,21311]debug:trueLet’s assume that the first two parameters are for a node named/lidar_ns/lidar_node_name, the next parameter is for a node named/imu, and the last parameter we want to set on both nodes.We would construct our ROS 2 parameters file as follows:/lidar_ns:lidar_node_name:ros__parameters:lidar_name:fooid:10imu:ros__parameters:ports:[2438,2439,2440]/**:ros__parameters:debug:trueNote the use of wildcards (/**) to indicate that the parameterdebugshould be set on any node in any namespace.Feature paritySome features of ROS 1 parameters files do not exist in ROS 2:Mixed types in a list is not supported yet (related issue)degandradsubstitutions are not supported + +Code Examples: + +Language: unknown +lidar_name:foolidar_id:10ports:[11312,11311,21311]debug:true + +Language: unknown +/lidar_ns:lidar_node_name:ros__parameters:lidar_name:fooid:10imu:ros__parameters:ports:[2438,2439,2440]/**:ros__parameters:debug:true diff --git "a/exported_docs/ros2/Migrating_Scripts\357\203\201.txt" "b/exported_docs/ros2/Migrating_Scripts\357\203\201.txt" new file mode 100644 index 0000000..ff5812a --- /dev/null +++ "b/exported_docs/ros2/Migrating_Scripts\357\203\201.txt" @@ -0,0 +1,22 @@ +Title: Migrating Scripts +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Scripts.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating ScriptsROS CLIIn ROS 1 there were individual commands for performing various actions, likerosrun,rosparam, etc.In ROS 2, there is a single top-level commands calledros2, and all of the actions are sub-commands of that, likeros2run,ros2param, etc.ROS CLI argumentsIn ROS 1, arguments to nodes were provided directly on the command-line.ROS 2 arguments should be scoped with--ros-argsand a trailing--(the trailing double dash may be elided if no arguments follow it).Remapping names is similar to ROS 1, taking on the formfrom:=to, except that it must be preceded by a--remap(or-r) flag. +For example:ros2runsome_packagesome_ros_executable--ros-args-rfoo:=barWe use a similar syntax for parameters, using the--param(or-p) flag:ros2runsome_packagesome_ros_executable--ros-args-pmy_param:=valueNote, this is different than using a leading underscore in ROS 1.To change a node name use__node(the ROS 1 equivalent is__name):ros2runsome_packagesome_ros_executable--ros-args-r__node:=new_node_nameNote the use of the-rflag. +The same remap flag is needed for changing the namespace__ns:ros2runsome_packagesome_ros_executable--ros-args-r__ns:=/new/namespaceThere is no equivalent in ROS 2 for the following ROS 1 keys:__log(but--log-config-filecan be used to provide a logger configuration file)__ip__hostname__masterFor more information, see thedesign document.Quick referenceFeatureROS 1ROS 2remappingfoo:=bar-r foo:=barparameters_foo:=bar-p foo:=barnode name__name:=foo-r __node:=foonamespace__ns:=foo-r __ns:=foo + +Code Examples: + +Language: unknown +ros2runsome_packagesome_ros_executable--ros-args-rfoo:=bar + +Language: unknown +ros2runsome_packagesome_ros_executable--ros-args-pmy_param:=value + +Language: unknown +ros2runsome_packagesome_ros_executable--ros-args-r__node:=new_node_name + +Language: unknown +ros2runsome_packagesome_ros_executable--ros-args-r__ns:=/new/namespace diff --git "a/exported_docs/ros2/Migrating_from_ROS_1_to_ROS_2\357\203\201.txt" "b/exported_docs/ros2/Migrating_from_ROS_1_to_ROS_2\357\203\201.txt" new file mode 100644 index 0000000..0e97b69 --- /dev/null +++ "b/exported_docs/ros2/Migrating_from_ROS_1_to_ROS_2\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Migrating from ROS 1 to ROS 2 +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating from ROS 1 to ROS 2These guides show how to convert existing ROS 1 packages to ROS 2. +If you are new to porting between ROS 1 and ROS 2, it is recommended to read through the guides in order.Migrating PackagesMigrating your package.xml to format 2Migrating InterfacesMigrating a C++ Package ExampleMigrating C++ Packages ReferenceMigrating a Python Package ExampleMigrating Python Packages ReferenceMigrating Launch FilesMigrating ParametersMigrating ScriptsAutomatic toolsThere are also some automatic conversion tools that exist, though they are not exhaustive:Magical ROS 2 Conversion ToolLaunch File migrator that converts a ROS 1 XML launch file to a ROS 2 Python launch file:https://github.com/aws-robotics/ros2-launch-file-migratorAmazon has made their tools for porting from ROS 1 to ROS 2 available at:https://github.com/awslabs/ros2-migration-tools/tree/master/porting_toolsrospy2Python project to automatically convert rospy calls to rclpy calls \ No newline at end of file diff --git "a/exported_docs/ros2/Migrating_your_package.xml_to_format_2\357\203\201.txt" "b/exported_docs/ros2/Migrating_your_package.xml_to_format_2\357\203\201.txt" new file mode 100644 index 0000000..5fef800 --- /dev/null +++ "b/exported_docs/ros2/Migrating_your_package.xml_to_format_2\357\203\201.txt" @@ -0,0 +1,54 @@ +Title: Migrating your package.xml to format 2 +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Migrating-from-ROS1/Migrating-Package-XML.html +Section: Installation +-------------------------------------------------------------------------------- + +Migrating your package.xml to format 2Table of ContentsPrerequisitesMigrate from format 1 to 2Addformatattribute toReplaceConvert sometoBegin usingSimplify dependencies withTest your newpackage.xmlROS 2 requirespackage.xmlfiles to use at leastformat 2. +This guide shows how to migrate apackage.xmlfrom format 1 to format 2.If thetag at the start of yourpackage.xmllooks like either of the following, then it is using format 1 and you must migrate it.PrerequisitesYou should have a working ROS 1 installation. +This enables you to check that the convertedpackage.xmlis valid by building and testing the package, since ROS 1 supports allpackage.xmlformat versions.Migrate from format 1 to 2Format 1 and format 2 differ in how they specify dependencies. +Read thecompatibility section in REP-0140for a summary of the differences.Addformatattribute toAdd or set theformatattribute to2to indicate that thepackage.xmluses format 2.ReplaceThetag is no longer allowed. +If you have a dependency specified like this:foothen replace it with one or both of these tags:foofooIf the dependency is needed when something in your package is executed, then use thetag. +If packages that depend on your package need the dependency when they are built, then use thetag. +Use both tags if you are unsure.Convert sometoIn format 1declares dependencies that are needed when running your package’s tests. +It still does that in format 2, but it additionally declares dependencies that are needed when building your package’s tests.Because of the limitations of this tag in format 1, your package may have a test-only dependency specified as alike this:testfooIf so, change it to a.testfooNoteIf you are using CMake, then make sure your test dependencies are only referenced within aif(BUILD_TESTING)block:if(BUILD_TESTING)find_package(testfooREQUIRED)endif()Begin usingUse the newtag to declare dependencies needed for building your package’s documentation. +For example, C++ packages might have this dependency:doxygenwhile Python packages might have this one:python3-sphinxSeethe guide on documenting ROS 2 packagesfor more information.Simplify dependencies withis a new tag that makespackage.xmlfiles more concise. +If yourpackage.xmlhas these three tags for the same dependency:foofoofoothen replace them with a singlelike this:fooTest your newpackage.xmlBuild and test your package as you normally do usingcatkin_make,cakin_make_isolated, or thecatkinbuild tool. +If everything succeeds, then yourpackage.xmlis valid. + +Code Examples: + +Language: unknown + + +Language: unknown + + +Language: unknown + + +Language: unknown +foo + +Language: unknown +foofoo + +Language: unknown +testfoo + +Language: unknown +testfoo + +Language: unknown +if(BUILD_TESTING)find_package(testfooREQUIRED)endif() + +Language: unknown +doxygen + +Language: unknown +python3-sphinx + +Language: unknown +foofoofoo + +Language: unknown +foo diff --git "a/exported_docs/ros2/Monitoring_for_parameter_changes_(C++)\357\203\201.txt" "b/exported_docs/ros2/Monitoring_for_parameter_changes_(C++)\357\203\201.txt" new file mode 100644 index 0000000..2d7969c --- /dev/null +++ "b/exported_docs/ros2/Monitoring_for_parameter_changes_(C++)\357\203\201.txt" @@ -0,0 +1,94 @@ +Title: Monitoring for parameter changes (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Monitoring-For-Parameter-Changes-CPP.html +Section: Installation +-------------------------------------------------------------------------------- + +Monitoring for parameter changes (C++)Goal:Learn to use the ParameterEventHandler class to monitor and respond to parameter changes.Tutorial level:IntermediateTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the C++ node3 Build and runSummaryRelated contentBackgroundOften a node needs to respond to changes to its own parameters or another node’s parameters. +The ParameterEventHandler class makes it easy to listen for parameter changes so that your code can respond to them. +This tutorial will show you how to use the C++ version of the ParameterEventHandler class to monitor for changes to a node’s own parameters as well as changes to another node’s parameters.PrerequisitesBefore starting this tutorial, you should first complete the following tutorials:Understanding parametersUsing parameters in a class (C++)TasksIn this tutorial, you will create a new package to contain some sample code, write some C++ code to use the ParameterEventHandler class, and test the resulting code.1 Create a packageFirst, open a new terminal andsource your ROS 2 installationso thatros2commands will work.Followthese instructionsto create a new workspace namedros2_ws.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +So, navigate intoros2_ws/srcand then create a new package there:ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_parameter_event_handler --dependencies rclcppYour terminal will return a message verifying the creation of your packagecpp_parameter_event_handlerand all its necessary files and folders.The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xmlorCMakeLists.txt. +As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.C++parametereventsclienttutorialYourNameApache-2.02 Write the C++ nodeInside theros2_ws/src/cpp_parameter_event_handler/srcdirectory, create a new file calledparameter_event_handler.cppand paste the following code within:#include#include"rclcpp/rclcpp.hpp"classSampleNodeWithParameters:publicrclcpp::Node{public:SampleNodeWithParameters():Node("node_with_parameters"){this->declare_parameter("an_int_param",0);// Create a parameter subscriber that can be used to monitor parameter changes// (for this node's parameters as well as other nodes' parameters)param_subscriber_=std::make_shared(this);// Set a callback for this node's integer parameter, "an_int_param"autocb=[this](constrclcpp::Parameter&p){RCLCPP_INFO(this->get_logger(),"cb: Received an update to parameter\"%s\"of type %s:\"%ld\"",p.get_name().c_str(),p.get_type_name().c_str(),p.as_int());};cb_handle_=param_subscriber_->add_parameter_callback("an_int_param",cb);}private:std::shared_ptrparam_subscriber_;std::shared_ptrcb_handle_;};intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.1 Examine the codeThe first statement,#includeis included so that the code can utilize the std::make_shared template. +The next,#include"rclcpp/rclcpp.hpp"is included to allow the code to reference the various functionality provided by the rclcpp interface, including the ParameterEventHandler class.After the class declaration, the code defines a class,SampleNodeWithParameters. +The constructor for the class declares an integer parameteran_int_param, with a default value of 0. +Next, the code creates aParameterEventHandlerthat will be used to monitor changes to parameters. +Finally, the code creates a lambda function and sets it as the callback to invoke wheneveran_int_paramis updated.NoteIt is very important to save the handle that is returned byadd_parameter_callback; otherwise, the callback will not be properly registered.SampleNodeWithParameters():Node("node_with_parameters"){this->declare_parameter("an_int_param",0);// Create a parameter subscriber that can be used to monitor parameter changes// (for this node's parameters as well as other nodes' parameters)param_subscriber_=std::make_shared(this);// Set a callback for this node's integer parameter, "an_int_param"autocb=[this](constrclcpp::Parameter&p){RCLCPP_INFO(this->get_logger(),"cb: Received an update to parameter\"%s\"of type %s:\"%ld\"",p.get_name().c_str(),p.get_type_name().c_str(),p.as_int());};cb_handle_=param_subscriber_->add_parameter_callback("an_int_param",cb);}Following theSampleNodeWithParametersis a typicalmainfunction which initializes ROS, spins the sample node so that it can send and receive messages, and then shuts down after the user enters ^C at the console.intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.2 Add executableTo build this code, first open theCMakeLists.txtfile and add the following lines of code below the dependencyfind_package(rclcppREQUIRED)add_executable(parameter_event_handler src/parameter_event_handler.cpp)ament_target_dependencies(parameter_event_handler rclcpp)install(TARGETSparameter_event_handlerDESTINATION lib/${PROJECT_NAME})3 Build and runIt’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro $ROS_DISTRO -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Navigate back to the root of your workspace,ros2_ws, and build your new package:colcon build --packages-select cpp_parameter_event_handlerOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bashcall install/setup.batNow run the node:ros2 run cpp_parameter_event_handler parameter_event_handlerThe node is now active and has a single parameter and will print a message whenever this parameter is updated. +To test this, open up another terminal and source the ROS setup file as before (. install/setup.bash) and execute the following command:ros2 param set node_with_parameters an_int_param 43The terminal running the node will display a message similar to the following:[INFO] [1606950498.422461764] [node_with_parameters]: cb: Received an update to parameter "an_int_param" of type integer: "43"The callback we set previously in the node has been invoked and has displayed the new updated value. +You can now terminate the running parameter_event_handler sample using ^C in the terminal.3.1 Monitor changes to another node’s parametersYou can also use the ParameterEventHandler to monitor parameter changes to another node’s parameters. +Let’s update the SampleNodeWithParameters class to also monitor for changes to a parameter in another node. +We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates.First update the constructor to add the following code after the existing code:// Now, add a callback to monitor any changes to the remote node's parameter. In this// case, we supply the remote node name.autocb2=[this](constrclcpp::Parameter&p){RCLCPP_INFO(this->get_logger(),"cb2: Received an update to parameter\"%s\"of type: %s:\"%.02lf\"",p.get_name().c_str(),p.get_type_name().c_str(),p.as_double());};autoremote_node_name=std::string("parameter_blackboard");autoremote_param_name=std::string("a_double_param");cb_handle2_=param_subscriber_->add_parameter_callback(remote_param_name,cb2,remote_node_name);Then add another member variable,cb_handle2for the additional callback handle:private:std::shared_ptrparam_subscriber_;std::shared_ptrcb_handle_;std::shared_ptrcb_handle2_;// Add this};In a terminal, navigate back to the root of your workspace,ros2_ws, and build your updated package as before:colcon build --packages-select cpp_parameter_event_handlerThen source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bashcall install/setup.batNow, to test monitoring of remote parameters, first run the newly-built parameter_event_handler code:ros2 run cpp_parameter_event_handler parameter_event_handlerNext, from another teminal (with ROS initialized), run the parameter_blackboard demo application, as follows:ros2 run demo_nodes_cpp parameter_blackboardFinally, from a third terminal (with ROS initialized), let’s set a parameter on the parameter_blackboard node:ros2 param set parameter_blackboard a_double_param 3.45Upon executing this command, you should see output in the parameter_event_handler window, indicating that the callback function was invoked upon the parameter update:[INFO] [1606952588.237531933] [node_with_parameters]: cb2: Received an update to parameter "a_double_param" of type: double: "3.45"SummaryYou created a node with a parameter and used the ParameterEventHandler class to set a callback to monitor changes to that parameter. +You also used the same class to monitor changes to a remote node. +The ParameterEventHandler is a convenient way to monitor for parameter changes so that you can then respond to the updated values.Related contentTo learn how to adapt ROS 1 parameter files for ROS 2, see theMigrating YAML parameter files from ROS 1 to ROS2tutorial. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_parameter_event_handler --dependencies rclcpp + +Language: unknown +C++parametereventsclienttutorialYourNameApache-2.0 + +Language: unknown +#include#include"rclcpp/rclcpp.hpp"classSampleNodeWithParameters:publicrclcpp::Node{public:SampleNodeWithParameters():Node("node_with_parameters"){this->declare_parameter("an_int_param",0);// Create a parameter subscriber that can be used to monitor parameter changes// (for this node's parameters as well as other nodes' parameters)param_subscriber_=std::make_shared(this);// Set a callback for this node's integer parameter, "an_int_param"autocb=[this](constrclcpp::Parameter&p){RCLCPP_INFO(this->get_logger(),"cb: Received an update to parameter\"%s\"of type %s:\"%ld\"",p.get_name().c_str(),p.get_type_name().c_str(),p.as_int());};cb_handle_=param_subscriber_->add_parameter_callback("an_int_param",cb);}private:std::shared_ptrparam_subscriber_;std::shared_ptrcb_handle_;};intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +SampleNodeWithParameters():Node("node_with_parameters"){this->declare_parameter("an_int_param",0);// Create a parameter subscriber that can be used to monitor parameter changes// (for this node's parameters as well as other nodes' parameters)param_subscriber_=std::make_shared(this);// Set a callback for this node's integer parameter, "an_int_param"autocb=[this](constrclcpp::Parameter&p){RCLCPP_INFO(this->get_logger(),"cb: Received an update to parameter\"%s\"of type %s:\"%ld\"",p.get_name().c_str(),p.get_type_name().c_str(),p.as_int());};cb_handle_=param_subscriber_->add_parameter_callback("an_int_param",cb);} + +Language: unknown +intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +add_executable(parameter_event_handler src/parameter_event_handler.cpp)ament_target_dependencies(parameter_event_handler rclcpp)install(TARGETSparameter_event_handlerDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y + +Language: unknown +colcon build --packages-select cpp_parameter_event_handler + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run cpp_parameter_event_handler parameter_event_handler + +Language: unknown +ros2 param set node_with_parameters an_int_param 43 + +Language: unknown +[INFO] [1606950498.422461764] [node_with_parameters]: cb: Received an update to parameter "an_int_param" of type integer: "43" + +Language: unknown +// Now, add a callback to monitor any changes to the remote node's parameter. In this// case, we supply the remote node name.autocb2=[this](constrclcpp::Parameter&p){RCLCPP_INFO(this->get_logger(),"cb2: Received an update to parameter\"%s\"of type: %s:\"%.02lf\"",p.get_name().c_str(),p.get_type_name().c_str(),p.as_double());};autoremote_node_name=std::string("parameter_blackboard");autoremote_param_name=std::string("a_double_param");cb_handle2_=param_subscriber_->add_parameter_callback(remote_param_name,cb2,remote_node_name); + +Language: unknown +private:std::shared_ptrparam_subscriber_;std::shared_ptrcb_handle_;std::shared_ptrcb_handle2_;// Add this}; + +Language: unknown +colcon build --packages-select cpp_parameter_event_handler + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run cpp_parameter_event_handler parameter_event_handler + +Language: unknown +ros2 run demo_nodes_cpp parameter_blackboard + +Language: unknown +ros2 param set parameter_blackboard a_double_param 3.45 + +Language: unknown +[INFO] [1606952588.237531933] [node_with_parameters]: cb2: Received an update to parameter "a_double_param" of type: double: "3.45" diff --git "a/exported_docs/ros2/Monitoring_for_parameter_changes_(Python)\357\203\201.txt" "b/exported_docs/ros2/Monitoring_for_parameter_changes_(Python)\357\203\201.txt" new file mode 100644 index 0000000..bf5bc6a --- /dev/null +++ "b/exported_docs/ros2/Monitoring_for_parameter_changes_(Python)\357\203\201.txt" @@ -0,0 +1,102 @@ +Title: Monitoring for parameter changes (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Monitoring-For-Parameter-Changes-Python.html +Section: Installation +-------------------------------------------------------------------------------- + +Monitoring for parameter changes (Python)Goal:Learn to use the ParameterEventHandler class to monitor and respond to parameter changes.Tutorial level:IntermediateTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the Python node3 Build and runSummaryRelated contentBackgroundOften a node needs to respond to changes to its own parameters or another node’s parameters. +The ParameterEventHandler class makes it easy to listen for parameter changes so that your code can respond to them. +This tutorial will show you how to use the Python version of the ParameterEventHandler class to monitor for changes to a node’s own parameters as well as changes to another node’s parameters.PrerequisitesBefore starting this tutorial, you should first complete the following tutorials:Understanding parametersUsing parameters in a class (Python)TasksIn this tutorial, you will create a new package to contain some sample code, write some Python code to use the ParameterEventHandler class, and test the resulting code.1 Create a packageFirst, open a new terminal andsource your ROS 2 installationso thatros2commands will work.Followthese instructionsto create a new workspace namedros2_ws.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +So, navigate intoros2_ws/srcand then create a new package there:ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameter_event_handler --dependencies rclpyYour terminal will return a message verifying the creation of your packagepython_parameter_event_handlerand all its necessary files and folders.The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xml. +As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.PythonparametereventsclienttutorialYourNameApache-2.02 Write the Python nodeInside theros2_ws/src/python_parameter_event_handler/python_parameter_event_handlerdirectory, create a new file calledparameter_event_handler.pyand paste the following code within:importrclpyimportrclpy.nodeimportrclpy.parameterfromrclpy.parameter_event_handlerimportParameterEventHandlerclassSampleNodeWithParameters(rclpy.node.Node):def__init__(self):super().__init__('node_with_parameters')self.declare_parameter('an_int_param',0)self.handler=ParameterEventHandler(self)self.callback_handle=self.handler.add_parameter_callback(parameter_name="an_int_param",node_name="node_with_parameters",callback=self.callback,)defcallback(self,p:rclpy.parameter.Parameter)->None:self.get_logger().info(f"Received an update to parameter:{p.name}:{rclpy.parameter.parameter_value_to_python(p.value)}")defmain():rclpy.init()node=SampleNodeWithParameters()rclpy.spin(node)rclpy.shutdown()2.1 Examine the codeTheimportstatements at the top are used to import the package dependencies.importrclpyimportrclpy.nodeimportrclpy.parameterfromrclpy.parameter_event_handlerimportParameterEventHandlerThe next piece of code creates the classSampleNodeWithParametersand the constructor. +The constructor for the class declares an integer parameteran_int_param, with a default value of 0. +Next, the code creates aParameterEventHandlerthat will be used to monitor changes to parameters.classSampleNodeWithParameters(rclpy.node.Node):def__init__(self):super().__init__('node_with_parameters')self.declare_parameter('an_int_param',0)self.handler=ParameterEventHandler(self)Finally, we add parameter callback and get callback handler for the new callback.NoteIt is very important to save the handle that is returned byadd_parameter_callback; otherwise, the callback will not be properly registered.self.callback_handle=self.handler.add_parameter_callback(parameter_name="an_int_param",node_name="node_with_parameters",callback=self.callback,)For the callback function, we use thecallbackmethod of theSampleNodeWithParametersclass.defcallback(self,p:rclpy.parameter.Parameter)->None:self.get_logger().info(f"Received an update to parameter:{p.name}:{rclpy.parameter.parameter_value_to_python(p.value)}")Following theSampleNodeWithParametersis a typicalmainfunction which initializes ROS, spins the sample node so that it can send and receive messages, and then shuts down after the user enters ^C at the console.defmain():rclpy.init()node=SampleNodeWithParameters()rclpy.spin(node)rclpy.shutdown()2.2 Add an entry pointOpen thesetup.pyfile. +Again, match themaintainer,maintainer_email,descriptionandlicensefields to yourpackage.xml:maintainer='YourName',maintainer_email='you@email.com',description='Python parameter tutorial',license='Apache-2.0',Add the following line within theconsole_scriptsbrackets of theentry_pointsfield:entry_points={'console_scripts':['node_with_parameters = python_parameter_event_handler.parameter_event_handler:main',],},3 Build and runIt’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro $ROS_DISTRO -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Navigate back to the root of your workspace,ros2_ws, and build your new package:colcon build --packages-select python_parameter_event_handlerOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bashcall install\setup.batNow run the node:ros2 run python_parameter_event_handler node_with_parametersThe node is now active and has a single parameter and will print a message whenever this parameter is updated. +To test this, open up another terminal and source the ROS setup file as before and execute the following command:ros2 param set node_with_parameters an_int_param 43The terminal running the node will display a message similar to the following:[INFO] [1698483083.315084660] [node_with_parameters]: Received an update to parameter: an_int_param: 43The callback we set previously in the node has been invoked and has displayed the new updated value. +You can now terminate the running parameter_event_handler sample using ^C in the terminal.3.1 Monitor changes to another node’s parametersYou can also use the ParameterEventHandler to monitor parameter changes to another node’s parameters. +Let’s update the SampleNodeWithParameters class to monitor for changes to a parameter in another node. +We will use the parameter_blackboard demo application to host a double parameter that we will monitor for updates.First update the constructor to add the following code after the existing code:def__init__(...):...self.callback_handle=self.handler.add_parameter_callback(parameter_name="a_double_param",node_name="parameter_blackboard",callback=self.callback,)In a terminal, navigate back to the root of your workspace,ros2_ws, and build your updated package as before:colcon build --packages-select python_parameter_event_handlerThen source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bashcall install\setup.batNow, to test monitoring of remote parameters, first run the newly-built parameter_event_handler code:ros2 run python_parameter_event_handler node_with_parametersNext, from another teminal (with ROS initialized), run the parameter_blackboard demo application, as follows:ros2 run demo_nodes_cpp parameter_blackboardFinally, from a third terminal (with ROS initialized), let’s set a parameter on the parameter_blackboard node:ros2 param set parameter_blackboard a_double_param 3.45Upon executing this command, you should see output in the parameter_event_handler window, indicating that the callback function was invoked upon the parameter update:[INFO] [1699821958.757770223] [node_with_parameters]: Received an update to parameter: a_double_param: 3.45SummaryYou created a node with a parameter and used the ParameterEventHandler class to set a callback to monitor changes to that parameter. +You also used the same class to monitor changes to a remote node. +The ParameterEventHandler is a convenient way to monitor for parameter changes so that you can then respond to the updated values.Related contentTo learn how to adapt ROS 1 parameter files for ROS 2, see theMigrating YAML parameter files from ROS 1 to ROS2tutorial. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameter_event_handler --dependencies rclpy + +Language: unknown +PythonparametereventsclienttutorialYourNameApache-2.0 + +Language: unknown +importrclpyimportrclpy.nodeimportrclpy.parameterfromrclpy.parameter_event_handlerimportParameterEventHandlerclassSampleNodeWithParameters(rclpy.node.Node):def__init__(self):super().__init__('node_with_parameters')self.declare_parameter('an_int_param',0)self.handler=ParameterEventHandler(self)self.callback_handle=self.handler.add_parameter_callback(parameter_name="an_int_param",node_name="node_with_parameters",callback=self.callback,)defcallback(self,p:rclpy.parameter.Parameter)->None:self.get_logger().info(f"Received an update to parameter:{p.name}:{rclpy.parameter.parameter_value_to_python(p.value)}")defmain():rclpy.init()node=SampleNodeWithParameters()rclpy.spin(node)rclpy.shutdown() + +Language: unknown +importrclpyimportrclpy.nodeimportrclpy.parameterfromrclpy.parameter_event_handlerimportParameterEventHandler + +Language: unknown +classSampleNodeWithParameters(rclpy.node.Node):def__init__(self):super().__init__('node_with_parameters')self.declare_parameter('an_int_param',0)self.handler=ParameterEventHandler(self) + +Language: unknown +self.callback_handle=self.handler.add_parameter_callback(parameter_name="an_int_param",node_name="node_with_parameters",callback=self.callback,) + +Language: unknown +defcallback(self,p:rclpy.parameter.Parameter)->None:self.get_logger().info(f"Received an update to parameter:{p.name}:{rclpy.parameter.parameter_value_to_python(p.value)}") + +Language: unknown +defmain():rclpy.init()node=SampleNodeWithParameters()rclpy.spin(node)rclpy.shutdown() + +Language: unknown +maintainer='YourName',maintainer_email='you@email.com',description='Python parameter tutorial',license='Apache-2.0', + +Language: unknown +entry_points={'console_scripts':['node_with_parameters = python_parameter_event_handler.parameter_event_handler:main',],}, + +Language: unknown +rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y + +Language: unknown +colcon build --packages-select python_parameter_event_handler + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install\setup.bat + +Language: unknown +ros2 run python_parameter_event_handler node_with_parameters + +Language: unknown +ros2 param set node_with_parameters an_int_param 43 + +Language: unknown +[INFO] [1698483083.315084660] [node_with_parameters]: Received an update to parameter: an_int_param: 43 + +Language: unknown +def__init__(...):...self.callback_handle=self.handler.add_parameter_callback(parameter_name="a_double_param",node_name="parameter_blackboard",callback=self.callback,) + +Language: unknown +colcon build --packages-select python_parameter_event_handler + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install\setup.bat + +Language: unknown +ros2 run python_parameter_event_handler node_with_parameters + +Language: unknown +ros2 run demo_nodes_cpp parameter_blackboard + +Language: unknown +ros2 param set parameter_blackboard a_double_param 3.45 + +Language: unknown +[INFO] [1699821958.757770223] [node_with_parameters]: Received an update to parameter: a_double_param: 3.45 diff --git "a/exported_docs/ros2/Nodes\357\203\201.txt" "b/exported_docs/ros2/Nodes\357\203\201.txt" new file mode 100644 index 0000000..c640236 --- /dev/null +++ "b/exported_docs/ros2/Nodes\357\203\201.txt" @@ -0,0 +1,11 @@ +Title: Nodes +URL: https://docs.ros.org/en/jazzy/Concepts/Basic/About-Nodes.html +Section: Installation +-------------------------------------------------------------------------------- + +NodesA node is a participant in the ROS 2 graph, which uses aclient libraryto communicate with other nodes. +Nodes can communicate with other nodes within the same process, in a different process, or on a different machine. +Nodes are typically the unit of computation in a ROS graph; each node should do one logical thing.Nodes canpublishto named topics to deliver data to other nodes, orsubscribeto named topics to get data from other nodes. +They can also act as aservice clientto have another node perform a computation on their behalf, or as aservice serverto provide functionality to other nodes. +For long-running computations, a node can act as anaction clientto have another node perform it on their behalf, or as anaction serverto provide functionality to other nodes. +Nodes can provide configurableparametersto change behavior during run-time.Nodes are often a complex combination of publishers, subscribers, service servers, service clients, action servers, and action clients, all at the same time.Connections between nodes are established through a distributeddiscoveryprocess. \ No newline at end of file diff --git "a/exported_docs/ros2/Overview_and_usage_of_RQt\357\203\201.txt" "b/exported_docs/ros2/Overview_and_usage_of_RQt\357\203\201.txt" new file mode 100644 index 0000000..ad6ccd7 --- /dev/null +++ "b/exported_docs/ros2/Overview_and_usage_of_RQt\357\203\201.txt" @@ -0,0 +1,25 @@ +Title: Overview and usage of RQt +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-RQt.html +Section: Installation +-------------------------------------------------------------------------------- + +Overview and usage of RQtTable of ContentsOverviewSystem setupInstalling From debsRQt Components StructureAdvantage of RQt frameworkFurther ReadingOverviewRQt is a graphical user interface framework that implements various tools and interfaces in the form of plugins. +One can run all the existing GUI tools as dockable windows within RQt. +The tools can still run in a traditional standalone method, but RQt makes it easier to manage all the various windows in a single screen layout.You can run any RQt tools/plugins easily by:rqtThis GUI allows you to choose any available plugins on your system. +You can also run plugins in standalone windows. +For example, RQt Python Console:ros2runrqt_py_consolerqt_py_consoleUsers can create their own plugins for RQt with eitherPythonorC++. +To see what RQt plugins are available for your system, run:ros2pkglistAnd then look for packages that start withrqt_.System setupInstalling From debssudoaptinstallros-jazzy-rqt*RQt Components StructureRQt consists of two metapackages:rqt- core infrastucture modules.rqt_common_plugins- Commonly useful debugging tools.Advantage of RQt frameworkCompared to building your own GUIs from scratch:Standardized common procedures for GUI (start-shutdown hook, restore previous states).Multiple widgets can be docked in a single window.Easily turn your existing Qt widgets into RQt plugins.Expect support atRobotics Stack Exchange(ROS community website for the questions).From system architecture’s perspective:Support multi-platform (basically whereverQTand ROS run) and multi-language (Python,C++).Manageable lifecycle: RQt plugins using a common API makes maintainance & reuse easier.Further ReadingROS 2 Discourseannouncement of porting to ROS 2)RQt for ROS 1 documentationBrief overview of RQt (froma Willow Garage intern blog post) + +Code Examples: + +Language: unknown +rqt + +Language: unknown +ros2runrqt_py_consolerqt_py_console + +Language: unknown +ros2pkglist + +Language: unknown +sudoaptinstallros-jazzy-rqt* diff --git "a/exported_docs/ros2/Package_Docs\357\203\201.txt" "b/exported_docs/ros2/Package_Docs\357\203\201.txt" new file mode 100644 index 0000000..9088f92 --- /dev/null +++ "b/exported_docs/ros2/Package_Docs\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Package Docs +URL: https://docs.ros.org/en/jazzy/Package-Docs.html +Section: Installation +-------------------------------------------------------------------------------- + +Package DocsROS package documentation, that is to say documentation for specific packages you install via apt or some other tool, can be found in multiple places. +Here is a brief list of where to look for specific ROS package documentation.Most ROS 2 packages have their package level documentationincluded in this index page.All ROS 2 package’s documentation is hosted alongside its information on theROS Index. Searching for packages on ROS Index will yield their information such as released distributions,README.mdfiles, URLs, and other important metadata.Larger PackagesLarger packages like MoveIt, Nav2, and microROS, are given their own domain or subdomain on ros.org. Here is a short list.MoveItNavigation2ControlmicroROS (embedded systems)API DocumentationYou can find the API level documentation for the ROS client libraries in the Jazzy distribution using the links below:rclcpp - C++ client libraryrclcpp_lifecycle - C++ lifecycle libraryrclcpp_components - C++ components libraryrclcpp_action - C++ actions libraryAdding Your Package to docs.ros.orgAll released ROS 2 packages are automatically added to docs.ros.org andROS Index. +If you would like to enable or configure your own package please see:Documenting a ROS 2 package. \ No newline at end of file diff --git "a/exported_docs/ros2/Quality_guide:_ensuring_code_quality\357\203\201.txt" "b/exported_docs/ros2/Quality_guide:_ensuring_code_quality\357\203\201.txt" new file mode 100644 index 0000000..99436a2 --- /dev/null +++ "b/exported_docs/ros2/Quality_guide:_ensuring_code_quality\357\203\201.txt" @@ -0,0 +1,45 @@ +Title: Quality guide: ensuring code quality +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Contributing/Quality-Guide.html +Section: Installation +-------------------------------------------------------------------------------- + +Quality guide: ensuring code qualityTable of ContentsStatic code analysis as part of the ament package buildStatic Thread Safety Analysis via Code AnnotationDynamic analysis (data races & deadlocks)This page gives guidance about how to improve the software quality of ROS 2 packages, focusing on more specific areas than the Quality Practices section of theDeveloper Guide.The sections below intend to address ROS 2 core, application and ecosystem packages and the core client libraries, C++ and Python. +The solutions presented are motivated by design and implementation considerations to improve quality attributes like “Reliability”, “Security”, “Maintainability”, “Determinism”, etc. which relate to non-functional requirements.Static code analysis as part of the ament package buildContext:You have developed your C++ production code.You have created a ROS 2 package with build support withament.Problem:Library level static code analysis is not run as part of the package build procedure.Library level static code analysis needs to be executed manually.Risk of forgetting to execute library level static code analysis before building +a new package version.Solution:Use the integration capabilities ofamentto execute static code analysis as +part of the package build procedure.Implementation:Insert into the packagesCMakeLists.txtfile....if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()... +endif()...Insert theament_linttest dependencies into the packagespackage.xmlfile.... +...ament_lint_autoament_lint_common... +Examples:rclcpp:rclcpp/rclcpp/CMakeLists.txtrclcpp/rclcpp/package.xmlrclcpp_lifecycle:rclcpp/rclcpp_lifecycle/CMakeLists.txtrclcpp/rclcpp_lifecycle/package.xmlResulting context:The static code analysis tools supported byamentare run as part of the package build.Static code analysis tools not supported byamentneed to be executed separately.Static Thread Safety Analysis via Code AnnotationContext:You are developing/debugging your multithreaded C++ production codeYou access data from multiple threads in C++ codeProblem:Data races and deadlocks can lead to critical bugs.Solution:Utilize Clang’s staticThread Safety Analysisby annotating threaded codeContext For Implementation:To enable Thread Safety Analysis, code must be annotated to let the compiler know more about the semantics of the code. +These annotations are Clang-specific attributes - e.g.__attribute__(capability())). +Instead of using those attributes directly, ROS 2 provides preprocessor macros that are erased when using other compilers.These macros can be found inrcpputils/thread_safety_annotations.hppThe Thread Safety Analysis documentation statesThread safety analysis can be used with any threading library, but it does require that the threading API be wrapped in classes and methods which have the appropriate annotationsWe have decided that we want ROS 2 developers to be able to usestd::threading primitives directly for their development. +We do not want to provide our own wrapped types as is suggested above.There are three C++ standard libraries to be aware ofThe GNU standard librarylibstdc++- default on Linux, explicitly via the compiler option-stdlib=libstdc++The LLVM standard librarylibc++(also calledlibcxx) - default on macOS, explicitly set by the compiler option-stdlib=libc++The Windows C++ Standard Library - not relevant to this use caselibcxxannotates itsstd::mutexandstd::lock_guardimplementations for Thread Safety Analysis. When using GNUlibstdc++, those annotations are not present, so Thread Safety Analysis cannot be used on non-wrappedstd::types.Therefore, to use Thread Safety Analysis directly withstd::types, we must uselibcxxImplementation:The code migration suggestions here are by no means complete - when writing (or annotating existing) threaded code, you are encouraged to utilize as many of the annotations as is logical for your use case. +However, this step-by-step is a great place to start!Enabling Analysis for Package/TargetWhen the C++ compiler is Clang, enable the-Wthread-safetyflag. Example below for CMake-based projectsif(CMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wthread-safety)# for your whole packagetarget_compile_options(${MY_TARGET}PUBLIC-Wthread-safety)# for a single library or executableendif()Annotating CodeStep 1 - Annotate data membersFind anywhere thatstd::mutexis used to protect some member dataAdd theRCPPUTILS_TSA_GUARDED_BY(mutex_name)annotation to the data that is protected by the mutexclassFoo{public:voidincr(intamount){std::lock_guardlock(mutex_);bar+=amount;}voidget()const{returnbar;}private:mutablestd::mutexmutex_;intbarRCPPUTILS_TSA_GUARDED_BY(mutex_)=0;};Step 2 - Fix WarningsIn the above example -Foo::getwill produce a compiler warning! To fix it, lock before returning barvoidget()const{std::lock_guardlock(mutex_);returnbar;}Step 3 - (Optional but Recommended) Refactor Existing Code to Private-Mutex PatternA recommended pattern in threaded C++ code is to always keep yourmutexas aprivate:member of the data structure. This makes data safety the concern of the containing structure, offloading that responsibility from users of the structure and minimizing the surface area of affected code.Making your locks private may require rethinking the interfaces to your data. This is a great exercise - here are a few things to considerYou may want to provide specialized interfaces for performing analysis that requires complex locking logic, e.g. counting members in a filtered set of a mutex-guarded map structure, instead of actually returning the underlying structure to consumersConsider copying to avoid blocking, where the amount of data is small. This can let other threads get on with accessing the shared data, which can potentially lead to better overall performance.Step 4 - (Optional) Enable Negative Capability Analysishttps://clang.llvm.org/docs/ThreadSafetyAnalysis.html#negative-capabilitiesNegative Capability Analysis lets you specify “this lock must not be held when calling this function”. It can reveal potential deadlock cases that other annotations cannot.Where you specified-Wthread-safety, add the additional flag-Wthread-safety-negativeOn any function that acquires a lock, use theRCPPUTILS_TSA_REQUIRES(!mutex)patternHow to run the analysisThe ROS CI build farm runs a nightly job withlibcxx, which will surface any issues in the ROS 2 core stack by being marked “Unstable” when Thread Safety Analysis raises warningsFor local runs, you have the following options, all equivalentUse the colconclang-libcxx mixin(see thedocumentationfor configuring mixins)colconbuild--mixinclang-libcxxPassing compiler to CMakecolconbuild--cmake-args-DCMAKE_C_COMPILER=clang-DCMAKE_CXX_COMPILER=clang++-DCMAKE_CXX_FLAGS='-stdlib=libc++ -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS'-DFORCE_BUILD_VENDOR_PKG=ON--no-warn-unused-cliOverriding system compilerCC=clangCXX=clang++colconbuild--cmake-args-DCMAKE_CXX_FLAGS='-stdlib=libc++ -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS'-DFORCE_BUILD_VENDOR_PKG=ON--no-warn-unused-cliResulting Context:Potential deadlocks and race conditions will be surfaced at compile time, when using Clang andlibcxxDynamic analysis (data races & deadlocks)Context:You are developing/debugging your multithreaded C++ production code.You use pthreads or C++11 threading + llvm libc++ (in case of ThreadSanitizer).You do not use Libc/libstdc++ static linking (in case of ThreadSanitizer).You do not build non-position-independent executables (in case of ThreadSanitizer).Problem:Data races and deadlocks can lead to critical bugs.Data races and deadlocks cannot be detected using static analysis (reason: limitation of static analysis).Data races and deadlocks must not show up during development debugging / testing (reason: usually not all possible control paths through production code exercised).Solution:Use a dynamic analysis tool which focuses on finding data races and deadlocks (here clang ThreadSanitizer).Implementation:Compile and link the production code with clang using the option-fsanitize=thread(this instruments the production code).In case different production code shall be executed during analysis consider conditional compilation e.g.ThreadSanitizers _has_feature(thread_sanitizer).In case some code shall not be instrumented considerThreadSanitizers _/*attribute*/_((no_sanitize(“thread”))).In case some files shall not be instrumented consider file or function-level exclusionThreadSanitizers blacklisting, more specific:ThreadSanitizers Sanitizer Special Case Listor withThreadSanitizers no_sanitize(“thread”)and use the option--fsanitize-blacklist.Resulting context:Higher chance to find data races and deadlocks in production code before deploying it.Analysis result may lack reliability, tool in beta phase stage (in case of ThreadSanitizer).Overhead due to production code instrumentation (maintenance of separate branches for instrumented/not instrumented production code, etc.).Instrumented code needs more memory per thread (in case of ThreadSanitizer).Instrumented code maps a lot virtual address space (in case of ThreadSanitizer). + +Code Examples: + +Language: unknown +...if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()... +endif()... + +Language: unknown +... +...ament_lint_autoament_lint_common... + + +Language: unknown +if(CMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wthread-safety)# for your whole packagetarget_compile_options(${MY_TARGET}PUBLIC-Wthread-safety)# for a single library or executableendif() + +Language: unknown +classFoo{public:voidincr(intamount){std::lock_guardlock(mutex_);bar+=amount;}voidget()const{returnbar;}private:mutablestd::mutexmutex_;intbarRCPPUTILS_TSA_GUARDED_BY(mutex_)=0;}; + +Language: unknown +voidget()const{std::lock_guardlock(mutex_);returnbar;} + +Language: unknown +colconbuild--mixinclang-libcxx + +Language: unknown +colconbuild--cmake-args-DCMAKE_C_COMPILER=clang-DCMAKE_CXX_COMPILER=clang++-DCMAKE_CXX_FLAGS='-stdlib=libc++ -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS'-DFORCE_BUILD_VENDOR_PKG=ON--no-warn-unused-cli + +Language: unknown +CC=clangCXX=clang++colconbuild--cmake-args-DCMAKE_CXX_FLAGS='-stdlib=libc++ -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS'-DFORCE_BUILD_VENDOR_PKG=ON--no-warn-unused-cli diff --git "a/exported_docs/ros2/Quality_of_Service_settings\357\203\201.txt" "b/exported_docs/ros2/Quality_of_Service_settings\357\203\201.txt" new file mode 100644 index 0000000..c0e74c4 --- /dev/null +++ "b/exported_docs/ros2/Quality_of_Service_settings\357\203\201.txt" @@ -0,0 +1,36 @@ +Title: Quality of Service settings +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html +Section: Installation +-------------------------------------------------------------------------------- + +Quality of Service settingsTable of ContentsOverviewQoS policiesComparison to ROS 1QoS profilesQoS compatibilitiesComparison to ROS 1QoS eventsMatched eventsOverviewROS 2 offers a rich variety of Quality of Service (QoS) policies that allow you to tune communication between nodes. +With the right set of Quality of Service policies, ROS 2 can be as reliable as TCP or as best-effort as UDP, with many, many possible states in between. +Unlike ROS 1, which primarily only supported TCP, ROS 2 benefits from the flexibility of the underlying DDS transport in environments with lossy wireless networks where a “best effort” policy would be more suitable, or in real-time computing systems where the right Quality of Service profile is needed to meet deadlines.A set of QoS “policies” combine to form a QoS “profile”. +Given the complexity of choosing the correct QoS policies for a given scenario, ROS 2 provides a set of predefined QoS profiles for common use cases (e.g. sensor data). +At the same time, developers are given the flexibility to control specific policies of the QoS profiles.QoS profiles can be specified for publishers, subscriptions, service servers and clients. +A QoS profile can be applied independently to each instance of the aforementioned entities, but if different profiles are used, it is possible that they will be incompatible, preventing the delivery of messages.QoS policiesThe base QoS profile currently includes settings for the following policies:HistoryKeep last: only store up to N samples, configurable via the queue depth option.Keep all: store all samples, subject to the configured resource limits of the underlying middleware.DepthQueue size: only honored if the “history” policy was set to “keep last”.ReliabilityBest effort: attempt to deliver samples, but may lose them if the network is not robust.Reliable: guarantee that samples are delivered, may retry multiple times.DurabilityTransient local: the publisher becomes responsible for persisting samples for “late-joining” subscriptions.Volatile: no attempt is made to persist samples.DeadlineDuration: the expected maximum amount of time between subsequent messages being published to a topicLifespanDuration: the maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired (expired messages are silently dropped and are effectively never received).LivelinessAutomatic: the system will consider all of the node’s publishers to be alive for another “lease duration” when any one of its publishers has published a message.Manual by topic: the system will consider the publisher to be alive for another “lease duration” if it manually asserts that it is still alive (via a call to the publisher API).Lease DurationDuration: the maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness (losing liveliness could be an indication of a failure).For each of the policies that is not a duration, there is also the option of “system default”, which uses the default of the underlying middleware. +For each of the policies that is a duration, there also exists a “default” option that means the duration is unspecified, which the underlying middleware will usually interpret as an infinitely long duration.Comparison to ROS 1The “history” and “depth” policies in ROS 2 combine to provide functionality akin to the queue size in ROS 1.The “reliability” policy in ROS 2 is akin to the use of either UDPROS (only inroscpp) for “best effort”, or TCPROS (ROS 1 default) for “reliable”. +Note however that even the reliable policy in ROS 2 is implemented using UDP, which allows for multicasting if appropriate.The “durability” policy “transient local”, combined with any depth, provides functionality similar to that of “latching” publishers. +The remaining policies in ROS 2 are not akin to anything that is available in ROS 1, meaning that ROS 2 is more featureful than ROS 1 in this respect. +It is possible that in the future, even more QoS policies will be available in ROS 2.QoS profilesProfiles allow developers to focus on their applications without worrying about every QoS setting possible. +A QoS profile defines a set of policies that are expected to go well together for a particular use case.The currently defined QoS profiles are:Default QoS settings for publishers and subscriptionsIn order to make the transition from ROS 1 to ROS 2 easier, exercising a similar network behavior is desirable. +By default, publishers and subscriptions in ROS 2 have “keep last” for history with a queue size of 10, “reliable” for reliability, “volatile” for durability, and “system default” for liveliness. +Deadline, lifespan, and lease durations are also all set to “default”.ServicesIn the same vein as publishers and subscriptions, services are reliable. +It is especially important for services to use volatile durability, as otherwise service servers that re-start may receive outdated requests. +While the client is protected from receiving multiple responses, the server is not protected from side-effects of receiving the outdated requests.Sensor dataFor sensor data, in most cases it’s more important to receive readings in a timely fashion, rather than ensuring that all of them arrive. +That is, developers want the latest samples as soon as they are captured, at the expense of maybe losing some. +For that reason the sensor data profile uses best effort reliability and a smaller queue size.ParametersParameters in ROS 2 are based on services, and as such have a similar profile. +The difference is that parameters use a much larger queue depth so that requests do not get lost when, for example, the parameter client is unable to reach the parameter service server.System defaultThis uses the RMW implementation’s default values for all of the policies. +Different RMW implementations may have different defaults.Click herefor the specific policies in use for the above profiles. +The settings in these profiles are subject to further tweaks, based on the feedback from the community.QoS compatibilitiesNote:This section refers to publishers and subscriptions but the content applies to service servers and clients in the same manner.QoS profiles may be configured for publishers and subscriptions independently. +A connection between a publisher and a subscription is only made if the pair has compatible QoS profiles.QoS profile compatibility is determined based on a “Request vs Offered” model. +Subscriptionsrequesta QoS profile that is the “minimum quality” that it is willing to accept, and publishersoffera QoS profile that is the “maximum quality” that it is able to provide. +Connections are only made if every policy of the requested QoS profile is not more stringent than that of the offered QoS profile. +Multiple subscriptions can be connected to a single publisher simultaneously even if their requested QoS profiles are different. +The compatibility between a publisher and a subscription is unaffected by the presence of other publishers and subscriptions.The following tables show the compatibility of the different policy settings and the result:Compatibility of reliability QoS policies:PublisherSubscriptionCompatibleBest effortBest effortYesBest effortReliableNoReliableBest effortYesReliableReliableYesCompatibility of durability QoS policies:PublisherSubscriptionCompatibleResultVolatileVolatileYesNew messages onlyVolatileTransient localNoNo communicationTransient localVolatileYesNew messages onlyTransient localTransient localYesNew and old messagesTo achieve a “latched” topic that is visible to late subscribers, +both the publisher and subscriber must agree to use ‘Transient Local’.Compatibility of deadline QoS policies:Assumexandyare arbitrary valid duration values.PublisherSubscriptionCompatibleDefaultDefaultYesDefaultxNoxDefaultYesxxYesxy(wherey>x)Yesxy(whereyx)Yesxy(wherey...tf2::Quaternionq;// Create a quaternion from roll/pitch/yaw in radians (0, 0, 0)q.setRPY(0,0,0);// Print the quaternion components (0, 0, 0, 1)RCLCPP_INFO(this->get_logger(),"%f %f %f %f",q.x(),q.y(),q.z(),q.w());The magnitude of a quaternion should always be one. +If numerical errors cause a quaternion magnitude other than one, ROS 2 will print warnings. +To avoid these warnings, normalize the quaternion:q.normalize();Quaternion types in ROS 2ROS 2 uses two quaternion datatypes:tf2::Quaternionand its equivalentgeometry_msgs::msg::Quaternion. +To convert between them in C++, use the methods oftf2_geometry_msgs.C++#include...tf2::Quaterniontf2_quat,tf2_quat_from_msg;tf2_quat.setRPY(roll,pitch,yaw);// Convert tf2::Quaternion to geometry_msgs::msg::Quaterniongeometry_msgs::msg::Quaternionmsg_quat=tf2::toMsg(tf2_quat);// Convert geometry_msgs::msg::Quaternion to tf2::Quaterniontf2::convert(msg_quat,tf2_quat_from_msg);// ortf2::fromMsg(msg_quat,tf2_quat_from_msg);Pythonfromgeometry_msgs.msgimportQuaternion...# Create a list of floats, which is compatible with tf2# Quaternion methodsquat_tf=[0.0,1.0,0.0,0.0]# Convert a list to geometry_msgs.msg.Quaternionmsg_quat=Quaternion(x=quat_tf[0],y=quat_tf[1],z=quat_tf[2],w=quat_tf[3])Quaternion operations1 Think in RPY then convert to quaternionIt’s easy for us to think of rotations about axes, but hard to think in terms of quaternions. +A suggestion is to calculate target rotations in terms of roll (about an X-axis), pitch (about the Y-axis), and yaw (about the Z-axis), and then convert to a quaternion.# quaternion_from_euler method is available in turtle_tf2_py/turtle_tf2_py/turtle_tf2_broadcaster.pyq=quaternion_from_euler(1.5707,0,-1.5707)print(f'The quaternion representation is x:{q[0]}y:{q[1]}z:{q[2]}w:{q[3]}.')2 Applying a quaternion rotationTo apply the rotation of one quaternion to a pose, simply multiply the previous quaternion of the pose by the quaternion representing the desired rotation. +The order of this multiplication matters.C++#include...tf2::Quaternionq_orig,q_rot,q_new;q_orig.setRPY(0.0,0.0,0.0);// Rotate the previous pose by 180* about Xq_rot.setRPY(3.14159,0.0,0.0);q_new=q_rot*q_orig;q_new.normalize();Pythonq_orig=quaternion_from_euler(0,0,0)# Rotate the previous pose by 180* about Xq_rot=quaternion_from_euler(3.14159,0,0)q_new=quaternion_multiply(q_rot,q_orig)3 Inverting a quaternionAn easy way to invert a quaternion is to negate the w-component:q[3]=-q[3]4 Relative rotationsSay you have two quaternions from the same frame,q_1andq_2. +You want to find the relative rotation,q_r, that convertsq_1toq_2in a following manner:q_2=q_r*q_1You can solve forq_rsimilarly to solving a matrix equation. +Invertq_1and right-multiply both sides. Again, the order of multiplication is important:q_r=q_2*q_1_inverseHere’s an example to get the relative rotation from the previous robot pose to the current robot pose in python:defquaternion_multiply(q0,q1):"""Multiplies two quaternions.Input:param q0: A 4 element array containing the first quaternion (q01, q11, q21, q31):param q1: A 4 element array containing the second quaternion (q02, q12, q22, q32)Output:return: A 4 element array containing the final quaternion (q03,q13,q23,q33)"""# Extract the values from q0w0=q0[0]x0=q0[1]y0=q0[2]z0=q0[3]# Extract the values from q1w1=q1[0]x1=q1[1]y1=q1[2]z1=q1[3]# Computer the product of the two quaternions, term by termq0q1_w=w0*w1-x0*x1-y0*y1-z0*z1q0q1_x=w0*x1+x0*w1+y0*z1-z0*y1q0q1_y=w0*y1-x0*z1+y0*w1+z0*x1q0q1_z=w0*z1+x0*y1-y0*x1+z0*w1# Create a 4 element array containing the final quaternionfinal_quaternion=np.array([q0q1_w,q0q1_x,q0q1_y,q0q1_z])# Return a 4 element array containing the final quaternion (q02,q12,q22,q32)returnfinal_quaternionq1_inv[0]=prev_pose.pose.orientation.xq1_inv[1]=prev_pose.pose.orientation.yq1_inv[2]=prev_pose.pose.orientation.zq1_inv[3]=-prev_pose.pose.orientation.w# Negate for inverseq2[0]=current_pose.pose.orientation.xq2[1]=current_pose.pose.orientation.yq2[2]=current_pose.pose.orientation.zq2[3]=current_pose.pose.orientation.wqr=quaternion_multiply(q2,q1_inv)SummaryIn this tutorial, you learned about the fundamental concepts of a quaternion and its related mathematical operations, like inversion and rotation. +You also learned about its usage examples in ROS 2 and conversion methods between two separate Quaternion classes. + +Code Examples: + +Language: unknown +#include...tf2::Quaternionq;// Create a quaternion from roll/pitch/yaw in radians (0, 0, 0)q.setRPY(0,0,0);// Print the quaternion components (0, 0, 0, 1)RCLCPP_INFO(this->get_logger(),"%f %f %f %f",q.x(),q.y(),q.z(),q.w()); + +Language: unknown +q.normalize(); + +Language: unknown +#include...tf2::Quaterniontf2_quat,tf2_quat_from_msg;tf2_quat.setRPY(roll,pitch,yaw);// Convert tf2::Quaternion to geometry_msgs::msg::Quaterniongeometry_msgs::msg::Quaternionmsg_quat=tf2::toMsg(tf2_quat);// Convert geometry_msgs::msg::Quaternion to tf2::Quaterniontf2::convert(msg_quat,tf2_quat_from_msg);// ortf2::fromMsg(msg_quat,tf2_quat_from_msg); + +Language: unknown +fromgeometry_msgs.msgimportQuaternion...# Create a list of floats, which is compatible with tf2# Quaternion methodsquat_tf=[0.0,1.0,0.0,0.0]# Convert a list to geometry_msgs.msg.Quaternionmsg_quat=Quaternion(x=quat_tf[0],y=quat_tf[1],z=quat_tf[2],w=quat_tf[3]) + +Language: unknown +# quaternion_from_euler method is available in turtle_tf2_py/turtle_tf2_py/turtle_tf2_broadcaster.pyq=quaternion_from_euler(1.5707,0,-1.5707)print(f'The quaternion representation is x:{q[0]}y:{q[1]}z:{q[2]}w:{q[3]}.') + +Language: unknown +#include...tf2::Quaternionq_orig,q_rot,q_new;q_orig.setRPY(0.0,0.0,0.0);// Rotate the previous pose by 180* about Xq_rot.setRPY(3.14159,0.0,0.0);q_new=q_rot*q_orig;q_new.normalize(); + +Language: unknown +q_orig=quaternion_from_euler(0,0,0)# Rotate the previous pose by 180* about Xq_rot=quaternion_from_euler(3.14159,0,0)q_new=quaternion_multiply(q_rot,q_orig) + +Language: unknown +q[3]=-q[3] + +Language: unknown +q_2=q_r*q_1 + +Language: unknown +q_r=q_2*q_1_inverse + +Language: unknown +defquaternion_multiply(q0,q1):"""Multiplies two quaternions.Input:param q0: A 4 element array containing the first quaternion (q01, q11, q21, q31):param q1: A 4 element array containing the second quaternion (q02, q12, q22, q32)Output:return: A 4 element array containing the final quaternion (q03,q13,q23,q33)"""# Extract the values from q0w0=q0[0]x0=q0[1]y0=q0[2]z0=q0[3]# Extract the values from q1w1=q1[0]x1=q1[1]y1=q1[2]z1=q1[3]# Computer the product of the two quaternions, term by termq0q1_w=w0*w1-x0*x1-y0*y1-z0*z1q0q1_x=w0*x1+x0*w1+y0*z1-z0*y1q0q1_y=w0*y1-x0*z1+y0*w1+z0*x1q0q1_z=w0*z1+x0*y1-y0*x1+z0*w1# Create a 4 element array containing the final quaternionfinal_quaternion=np.array([q0q1_w,q0q1_x,q0q1_y,q0q1_z])# Return a 4 element array containing the final quaternion (q02,q12,q22,q32)returnfinal_quaternionq1_inv[0]=prev_pose.pose.orientation.xq1_inv[1]=prev_pose.pose.orientation.yq1_inv[2]=prev_pose.pose.orientation.zq1_inv[3]=-prev_pose.pose.orientation.w# Negate for inverseq2[0]=current_pose.pose.orientation.xq2[1]=current_pose.pose.orientation.yq2[2]=current_pose.pose.orientation.zq2[3]=current_pose.pose.orientation.wqr=quaternion_multiply(q2,q1_inv) diff --git "a/exported_docs/ros2/RHEL_(RPM_packages)\357\203\201.txt" "b/exported_docs/ros2/RHEL_(RPM_packages)\357\203\201.txt" new file mode 100644 index 0000000..552ab0a --- /dev/null +++ "b/exported_docs/ros2/RHEL_(RPM_packages)\357\203\201.txt" @@ -0,0 +1,66 @@ +Title: RHEL (RPM packages) +URL: https://docs.ros.org/en/jazzy/Installation/RHEL-Install-RPMs.html +Section: Installation +-------------------------------------------------------------------------------- + +RHEL (RPM packages)Table of ContentsResourcesSystem setupSet localeEnable required repositoriesInstall development tools (optional)Install ROS 2Install additional RMW implementations (optional)Setup environmentTry some examplesNext stepsTroubleshootUninstallRPM packages for ROS 2 Jazzy Jalisco are currently available for RHEL 9. +The target platforms are defined inREP 2000.ResourcesStatus Page:ROS 2 Jazzy (RHEL 9):amd64Jenkins InstanceRepositoriesSystem setupSet localeMake sure you have a locale which supportsUTF-8. +If you are in a minimal environment (such as a docker container), the locale may be something minimal likeC. +We test with the following settings. However, it should be fine if you’re using a different UTF-8 supported locale.locale# check for UTF-8sudodnfinstalllangpacks-englibc-langpack-enexportLANG=en_US.UTF-8 + +locale# verify settingsEnable required repositoriesYou will need to enable the EPEL repositories and the PowerTools repository:sudodnfinstall'dnf-command(config-manager)'epel-release-y +sudodnfconfig-manager--set-enabledcrbNoteThis step may be slightly different depending on the distribution you are using. Check the EPEL documentation:https://docs.fedoraproject.org/en-US/epel/#_quickstartNext, download the ROS 2 .repo file:sudodnfinstallcurl +sudocurl--output/etc/yum.repos.d/ros2.repohttp://packages.ros.org/ros2/rhel/ros2.repoThen, update your metadata cache. +DNF may prompt you to verify the GPG key, which should match the locationhttps://raw.githubusercontent.com/ros/rosdistro/master/ros.asc.sudodnfmakecacheInstall development tools (optional)If you are going to build ROS packages or otherwise do development, you can also install the development tools:sudodnfinstall-y\cmake\gcc-c++\git\make\patch\python3-colcon-common-extensions\python3-mypy\python3-pip\python3-pydocstyle\python3-pytest\python3-pytest-repeat\python3-pytest-rerunfailures\python3-rosdep\python3-setuptools\python3-vcstool\wget# install some pip packages needed for testing and# not available as RPMspython3-mpipinstall-U--user\flake8-blind-except==0.1.1\flake8-class-newline\flake8-deprecatedInstall ROS 2ROS 2 packages are built on frequently updated RHEL systems. +It is always recommended that you ensure your system is up to date before installing new packages.sudodnfupdateDesktop Install (Recommended): ROS, RViz, demos, tutorials.sudodnfinstallros-jazzy-desktopROS-Base Install (Bare Bones): Communication libraries, message packages, command line tools. +No GUI tools.sudodnfinstallros-jazzy-ros-baseInstall additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at runtime. +See theguideon how to work with multiple RMWs.Setup environmentSet up your environment by sourcing the following file.# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zshsource/opt/ros/jazzy/setup.bashTry some examplesIf you installedros-jazzy-desktopabove you can try some examples.In one terminal, source the setup file and then run a C++talker:source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_cpptalkerIn another terminal source the setup file and then run a Pythonlistener:source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you need to uninstall ROS 2 or switch to a source-based install once you +have already installed from binaries, run the following command:sudodnfremoveros-jazzy-* + +Code Examples: + +Language: unknown +locale# check for UTF-8sudodnfinstalllangpacks-englibc-langpack-enexportLANG=en_US.UTF-8 + +locale# verify settings + +Language: unknown +sudodnfinstall'dnf-command(config-manager)'epel-release-y +sudodnfconfig-manager--set-enabledcrb + +Language: unknown +sudodnfinstallcurl +sudocurl--output/etc/yum.repos.d/ros2.repohttp://packages.ros.org/ros2/rhel/ros2.repo + +Language: unknown +sudodnfmakecache + +Language: unknown +sudodnfinstall-y\cmake\gcc-c++\git\make\patch\python3-colcon-common-extensions\python3-mypy\python3-pip\python3-pydocstyle\python3-pytest\python3-pytest-repeat\python3-pytest-rerunfailures\python3-rosdep\python3-setuptools\python3-vcstool\wget# install some pip packages needed for testing and# not available as RPMspython3-mpipinstall-U--user\flake8-blind-except==0.1.1\flake8-class-newline\flake8-deprecated + +Language: unknown +sudodnfupdate + +Language: unknown +sudodnfinstallros-jazzy-desktop + +Language: unknown +sudodnfinstallros-jazzy-ros-base + +Language: unknown +# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zshsource/opt/ros/jazzy/setup.bash + +Language: unknown +source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_cpptalker + +Language: unknown +source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_pylistener + +Language: unknown +sudodnfremoveros-jazzy-* diff --git "a/exported_docs/ros2/RHEL_(binary)\357\203\201.txt" "b/exported_docs/ros2/RHEL_(binary)\357\203\201.txt" new file mode 100644 index 0000000..f33f37b --- /dev/null +++ "b/exported_docs/ros2/RHEL_(binary)\357\203\201.txt" @@ -0,0 +1,67 @@ +Title: RHEL (binary) +URL: https://docs.ros.org/en/jazzy/Installation/Alternatives/RHEL-Install-Binary.html +Section: Installation +-------------------------------------------------------------------------------- + +RHEL (binary)Table of ContentsSystem requirementsSystem setupSet localeEnable required repositoriesInstall prerequisitesInstall development tools (optional)Install ROS 2Install dependencies using rosdepInstall additional RMW implementations (optional)Setup environmentTry some examplesNext stepsTroubleshootUninstallThis page explains how to install ROS 2 on RHEL from a pre-built binary package.NoteThe pre-built binary does not include all ROS 2 packages. +All packages in theROS base variantare included, and only a subset of packages in theROS desktop variantare included. +The exact list of packages are described by the repositories listed inthis ros2.repos file.There are alsoRPM packagesavailable.System requirementsWe currently support RHEL 9 64-bit.System setupSet localeMake sure you have a locale which supportsUTF-8. +If you are in a minimal environment (such as a docker container), the locale may be something minimal likeC. +We test with the following settings. However, it should be fine if you’re using a different UTF-8 supported locale.locale# check for UTF-8sudodnfinstalllangpacks-englibc-langpack-enexportLANG=en_US.UTF-8 + +locale# verify settingsEnable required repositoriesThe rosdep database contains packages from the EPEL and PowerTools repositories, which are not enabled by default. +They can be enabled by running:sudodnfinstall'dnf-command(config-manager)'epel-release-y +sudodnfconfig-manager--set-enabledcrbNoteThis step may be slightly different depending on the distribution you are using. Check the EPEL documentation:https://docs.fedoraproject.org/en-US/epel/#_quickstartInstall prerequisitesThere are a few packages that must be installed in order to get and unpack the binary release.sudodnfinstalltarbzip2wget-yInstall development tools (optional)If you are going to build ROS packages or otherwise do development, you can also install the development tools:sudodnfinstall-y\cmake\gcc-c++\git\make\patch\python3-colcon-common-extensions\python3-mypy\python3-pip\python3-pydocstyle\python3-pytest\python3-pytest-repeat\python3-pytest-rerunfailures\python3-rosdep\python3-setuptools\python3-vcstool\wget# install some pip packages needed for testing and# not available as RPMspython3-mpipinstall-U--user\flake8-blind-except==0.1.1\flake8-class-newline\flake8-deprecatedInstall ROS 2Go to thereleases pageDownload the latest package for RHEL; let’s assume that it ends up at~/Downloads/ros2-package-linux-x86_64.tar.bz2.Note: there may be more than one binary download option which might cause the file name to differ.Unpack it:mkdir-p~/ros2_jazzycd~/ros2_jazzy +tarxf~/Downloads/ros2-package-linux-x86_64.tar.bz2Install dependencies using rosdepROS 2 packages are built on frequently updated RHEL systems. +It is always recommended that you ensure your system is up to date before installing new packages.sudodnfupdatesudorosdepinit +rosdepupdate +rosdepinstall--from-paths~/ros2_jazzy/ros2-linux/share--ignore-src-y--skip-keys"cyclonedds fastcdr fastrtps iceoryx_binding_c rti-connext-dds-6.0.1 urdfdom_headers"Install additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at runtime. +See theguideon how to work with multiple RMWs.Setup environmentSet up your environment by sourcing the following file.# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zsh.~/ros2_jazzy/ros2-linux/setup.bashTry some examplesIn one terminal, source the setup file and then run a C++talker:.~/ros2_jazzy/ros2-linux/setup.bash +ros2rundemo_nodes_cpptalkerIn another terminal source the setup file and then run a Pythonlistener:.~/ros2_jazzy/ros2-linux/setup.bash +ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you installed your workspace with colcon as instructed above, “uninstalling” could be just a matter of opening a new terminal and not sourcing the workspace’ssetupfile. +This way, your environment will behave as though there is no Jazzy install on your system.If you’re also trying to free up space, you can delete the entire workspace directory with:rm-rf~/ros2_jazzy + +Code Examples: + +Language: unknown +locale# check for UTF-8sudodnfinstalllangpacks-englibc-langpack-enexportLANG=en_US.UTF-8 + +locale# verify settings + +Language: unknown +sudodnfinstall'dnf-command(config-manager)'epel-release-y +sudodnfconfig-manager--set-enabledcrb + +Language: unknown +sudodnfinstalltarbzip2wget-y + +Language: unknown +sudodnfinstall-y\cmake\gcc-c++\git\make\patch\python3-colcon-common-extensions\python3-mypy\python3-pip\python3-pydocstyle\python3-pytest\python3-pytest-repeat\python3-pytest-rerunfailures\python3-rosdep\python3-setuptools\python3-vcstool\wget# install some pip packages needed for testing and# not available as RPMspython3-mpipinstall-U--user\flake8-blind-except==0.1.1\flake8-class-newline\flake8-deprecated + +Language: unknown +mkdir-p~/ros2_jazzycd~/ros2_jazzy +tarxf~/Downloads/ros2-package-linux-x86_64.tar.bz2 + +Language: unknown +sudodnfupdate + +Language: unknown +sudorosdepinit +rosdepupdate +rosdepinstall--from-paths~/ros2_jazzy/ros2-linux/share--ignore-src-y--skip-keys"cyclonedds fastcdr fastrtps iceoryx_binding_c rti-connext-dds-6.0.1 urdfdom_headers" + +Language: unknown +# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zsh.~/ros2_jazzy/ros2-linux/setup.bash + +Language: unknown +.~/ros2_jazzy/ros2-linux/setup.bash +ros2rundemo_nodes_cpptalker + +Language: unknown +.~/ros2_jazzy/ros2-linux/setup.bash +ros2rundemo_nodes_pylistener + +Language: unknown +rm-rf~/ros2_jazzy diff --git "a/exported_docs/ros2/ROSCon_Talks\357\203\201.txt" "b/exported_docs/ros2/ROSCon_Talks\357\203\201.txt" new file mode 100644 index 0000000..7ac7cac --- /dev/null +++ "b/exported_docs/ros2/ROSCon_Talks\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: ROSCon Talks +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/ROSCon-Content.html +Section: Installation +-------------------------------------------------------------------------------- + +ROSCon TalksThe followingROSContalks have been given on ROS 2 and provide information about the workings of ROS 2 and various demos:20242023202220212020201920182017201620152014TitleLinksSaving lives sooner: leveraging ROS 2 for end-stage kidney diseasevideoThe State of ROS: Beneath the KiltvideoRMW Zenoh: An alternative middleware for ROS 2videoThe State of the InfrastructurevideoIn the Spot Light: Controlling Spot with ROS 2videoPanel: Successfully Deploying ROS 2 Into ProductionvideoExecutors in ROS 2videoThe Multithreaded Events ExecutorvideoAccelerating Robotics Development with Embedded LinuxvideoReal-time ROS 2 applications made easy with cactus-rtvideoSomething big is coming in ros2_control with ROS 2 Jazzy!videoHow to Use a Dragon’s Algorithm: Integrating Drake with MoveIt 2videoMore than just an actuator – Better ROS support for a manipulatorvideoA ROS 2 Package for Dynamic Collision Avoidance Based On On-Board Prox…videoGSplines: Generalized Splines for Motion Optimization and Smooth Colli…videoKOI and EBIKE: Optimizing Kinematics Structures and IK Parameters by C…videoA Fuzzy-Matching Trajectory Cache for MoveIt 2videoiceoryx2: A Journey to Becoming a First-Class RMW AlternativevideoJ1939 CAN Device Support in ROS 2videoIntegration of ETSI ITS messages for V2X communication in ROSvideoUnlocking the Potential of the Nicla Vision Board with ROS / ROS 2videoWe Hate Serial: Experiments using CAN-FD as a transport layer for micro-ROSvideoROS 2 Gateway to Professional 24/7 ApplicationsvideoOptimizing Gazebo simulation: Challenges in building complex simulatio…videoBuilding Humanoid Robots: Mastering Design and Control with ROSvideoURDF Creator: Bridging the Gap Between Learning and Applying ROS 2videoEnabling ROS 2 Benchmarks: A Medical Robotics PerspectivevideoScenario Execution for Robotics: A generic, backend-agnostic library f…video⚡Lightning Talks⚡videoMobile Robotics Scale-up Leveraging ROSvideoThe State of GazebovideoThe State of Open-RMFvideoMigrating a Mobile Manipulator to ROS 2videoJazzy Jalisco rosbag2 updates and new featuresvideo⚡ Lightning Talks ⚡videoHow is my robot? - On the state of ROS DiagnosticsvideoAccelerating the CI/CD-to-robot cycle by 10x for 1/10th the costvideor2s: A Terminal User Interface for ROS 2videoThe Lighthouse project: from Virtual Reality to Onboard Positioning for RoboticsvideoBuilding system packages with colcon in your own compact buildfarmvideorobot_folders – your favorite meta-workspace managervideoScaling Open-RMF from a Test Bench → Lab → Controlled Environment → ProductionvideoOpen-RMF and the Challenge of Resource Contention in Large-Scale Robot FleetsvideoROS in Large-scale Factory AutomationvideoEnhancing Robotic Communication & Scalability with Topic Keys in ROS 2videoROS 2 (and DDS) Compatible Selective Large Data TransfervideoAgent-based AI Framework for ROS 2videoros2ai Next-Gen ROS 2 CLI empowered by OpenAIvideoBuilding Foundation Model-powered Robots with ROS: A SurveyvideoScenic for ROS: A Probabilistic Programming Language for World Modelin…videoSoftware Platform Design and SDK Development for ROS 2-based LG AI Com…videoBeluga AMCL: A modern Monte Carlo Localization implementation for ROSvideoRadar Tracks for Path Planning in the presence of Dynamic ObstaclesvideoOn Use of Nav2 DockingvideoROS robot health monitoring: the Bonsai approachvideoNavigation à la carte: choose navigation profile and strategy as you govideoTitleLinksBuilding the iRobot® Create® 3 Robot: Challenges and Solutions for ROS…videoThe State of ROS: From the Iron Age to the Jazzy AgevideoROS 2 Types On-the-wire: Type Descriptions and Hashing in Iron and onwardsvideoReleasing a new ROS 2 distributionvideoPanel: Getting Involved with ROS as an OrganizationvideoLicensing of ROS Packages: Changes to package.xml and new tool supportvideoSDFormat: A robot description format in constant evolutionvideoRepeatable Reproducible Accessible ROS Development via Dev ContainersvideoColcon-in-container: say bye to the “it builds on my machine” syndromevideoROS with Kubernetes/KubeEdgevideoA New ROS 2 Driver for FANUC Robots Utilizing Ethernet/IPvideoA ROS 2 Package for Online Cobots Impedance ModulationvideoReal-Time Motion Control in ROS: Uniting HAL with Tormach’s ZA6 RobotvideoA safe and secure ROS 2 multi-domain architecture for AMD embedded het…videoOptimizing MoveIt - Costs, Constraints and BettermentsvideoLeveraging a functional approach for more testable and maintainable ROS codevideoReal-time Data-flow extension for ROS 2videoAn Integrated Modelling and Testing Architecture for ROS NodesvideoBreaking Bots: Robustness Testing for ROSvideoRclex on Nerves: a bare minimum runtime platform for ROS 2 nodes in ElixirvideoOn Use of Nav2 MPPI ControllervideoBidirectional navigation with Nav2videoAutonomous Robot Navigation and Localization on 3D Mesh Surfaces in ROSvideoROS 2 powered Android VHAL.video⚡Lightning Talks⚡videoUp, Up, and Away: Adventures in Aerial RoboticsvideoNEXUS: A ROS 2 framework for orchestrating industrial robotic lines and cellsvideoAerostack2: A framework for developing Multi-Robot Aerial SystemsvideoCreating scalable customized robotic platformsvideoCreate® 3 Robot in the Classroom: Teaching ROS 2 to UndergraduatesvideoROS 2 On the Browser with WebAssembly for Teaching Roboticsvideo⚡Lightning Talks⚡videoOctomap is dead: long life BonxaivideoParameters Should be BoringvideoUsing Reference System to evaluate features and performance in a stand…videoRosLibRust: Why we built it, why you might want to use it…videoLeveraging Secure Discovery Server in ROS 2videoSimulate your World: A deeper look at extending GazebovideoSimulate robots like never before with Open 3D EnginevideoSimulation of Highly Dynamic Omnidirectional Robots in Isaac SimvideoAn Integrated Distributed Simulation Environment weaving by Hakoniwa and mROS 2videoMulti-drone simulation with deep q-learningvideoSupporting Robotic Deliberation: The Deliberation Working Group and To…videoFlexBE - The Flexible Behavior Engine: Collaborative Autonomy in ROS 2videoSkiROS2 - A skill-based Robot Control Platform for ROSvideoMastering your ROS system state with Petri netsvideoSpatialVision: Bringing Popping-Out RViz to Life with AirPodsvideoWhat is Robotics Observability? Scaling ROS from Prototype to ProductionvideoSurviving the Flood (of Rosbags)videoImproving Your Application’s Algorithms and Optimizing Performance Usi…videoROSBag2NuScenes: Share the Bags, Spread the Joy - Autonomous Vehicle R…videoPostgreSQL / PostGIS to ROS 2 Bridge for Spatial DatavideoEfficient data recording and replaying in ROS 2videoDeveloping on ROS while ScalingvideoTitleLinksPanel: The ROS 2 Developer ExperiencevideoWearable ROS: Development of wearable robot system using ROS 2videoBuilding ROS 2 enabled Android apps with C++videoDistributed Robotics Simulator with Unreal EnginevideoTools and processes for improving the certifiability of ROS 2videoFailover ROS Framework : Consensus-based node redundancyvideoROS 2 and Gazebo Integration Best PracticesvideoChain-Aware ROS Evaluation Tool (CARET)videoROS 2 network monitoringvideoHow custom tasks are defined, assigned, and executed in Open-RMFvideoA practitioner’s guide to ros2_controlvideoZenoh: How to Make ROS 2 Work at any Scale and Integrate with AnythingvideoA case study in optics manufacturing with MoveIt2 and ros2_controlvideo20/20 Robot Vision - How to setup cameras in ROS 1 & ROS 2 using camera_aravisvideoFilter your ROS 2 contentvideoEvolving Message Types, and Other Interfaces, Over TimevideoMigrating from ROS1 to ROS 2 - choosing the right bridgevideoOn Use of Nav2 Smac PlannersvideoBazel and ROS 2 – building large scale safety applicationsvideoNative Rust components for ROS 2videoThe ROS build farm and you: How ROS packages you release become binary packages.videomROS 2: yet another runtime environment onto embedded devicesvideoROS 2 & Edge Impulse: Embedded AI in robotics applicationsvideomicro-ROS goes Automotive: supporting AUTOSAR-based microcontrollersvideoAn open architecture for Hardware Acceleration in ROS 2videoROS 2 and the Crazyflie: Aerial swarms and Autonomy with a tiny flying robotvideoA Raspberry Pi image with ROS 2 + RT and a customizable image buildervideoTitleLinksSMACC2videorospy2: Convert a ROS1 node to ROS2 by changing only one line of codevideoHello Robot: Democratizing Mobile Manipulation with ROSvideoChallenges for ROS2 in Autonomous Agricultural ApplicationsvideoESP32 microcontroller robot with Navigation 2 ROS 2 running in the CloudvideoMiddleware interconnecting ROS/ROS2 with the EtherCAT protocolvideoBuild and Manage Cloud-enhanced ROS Robots with AWS IoT Greengrass 2.0videoDriving Autonomy in Mobile Robotics with ROS2 and PX4videoIntegrating ROS 2 with existing DDS networksvideoVIPER: Volatiles Investigating Polar Exploration RovervideoChronicles of Caching and Containerising CI for Nav2videoA New Way to Interact with PointCloud2 MessagesvideoROS 2 Grasp Library – Acceleration for 3D Object Pose Detectionvideoros2_control: The future of ros_controlvideoROS 2 Rolling RidleyvideoHybrid Planning - Enabling Reactive Manipulation with MoveIt 2videoApex.OS Cert: Taking ROS 2 from prototype into productionvideoMaking a robot ROS 2 powered - a case study using the UR manipulatorsvideoOnline Trajectory Generation and Admittance Control in ROS2videoVSCode, Docker and ROS2videoROS 2 Content Filtered TopicsvideoRosbag2 for Power UsersvideoWe Have Ignition: The Next Generation of Gazebo SimulationvideoUsing NVIDIA Isaac Sim For Synthetic Data Generation & ROS DevelopmentvideoAugmented Reality and RoboticsvideoModeling sensors for simulation of ROS applications in UnityvideoPanel: Simulation Tools for ROSvideoTitleLinksAccelerating Innovation with ROS: Lessons in HealthcarevideoPanel: Software Quality in RoboticsvideoPanel: ROS AgriculturevideoAchieving Generality and Robustness in Semantic SegmentationvideoNavigation2: The Next Generation Navigation SystemvideoCHAMP Quadruped ControlvideoKiwibot: ROS2 in the atoms delivery industryvideoMoveItWorldvideoOpenCVvideoROBOTIS TurtleBot3videoAutowarevideoDronecodevideoFIWAREvideoLightning Talks and Sponsor Videos 1videoLightning Talks and Sponsor Videos 2videoLightning Talks and Sponsor Videos 3videoLightning Talks and Sponsor Videos 4videoTitleLinksMigrating a large ROS 1 codebase to ROS 2slides/videoThe New Architecture of Gazebo Wrappers for ROS 2slides/videoMigrating to ROS 2: Advice from Rover Roboticsslides/videoROS 2 on VxWorksslides/videoNavigation2 Overviewslides/videoLaunch Testing - Launch description and integration testing for ros2slides/videoROS 2 for Consumer Robotics: : The iRobot use-caseslides/videoComposable Nodes in ROS2slides/videoConcurrency in ROS 1 and ROS 2slides/videoA True Zero-Copy RMW Implementation for ROS2slides/videoROS2 Real-Time Behavior: Static Memory AllocationvideoPackML2: State Machine Based System Programming, Monitoring and Control in ROS2slides/videoQuality of Service Policies for ROS2 Communicationsslides/videoMicro-ROS: ROS2 on Microcontrollersslides/videoROS2 on Large Scale Systems: Discovery ServervideoBridging Your Transitions from ROS 1 to ROS 2slides/videoMarkup Extensions for ROS 2 Launchslides/videoTitleLinksHands-on ROS 2: A Walkthroughslides/videoLaunch for ROS 2slides/videoTitleLinksThe ROS 2 vision for advancing the future of robotics developmentslides/videoTitleLinksROS 2 Update - summary of alpha releases, architectural overviewslides/videoEvaluating the resilience of ROS2 communication layerslides/videoTitleLinksState of ROS 2 - demos and the technology behindslides/videoROS 2 on “small” embedded systemsslides/videoReal-time control in ROS and ROS 2slides/videoTitleLinksWhy you want to use ROS 2slides/videoNext-generation ROS: Building on DDSslides/video \ No newline at end of file diff --git "a/exported_docs/ros2/ROS_2_Core_Maintainer_Guide\357\203\201.txt" "b/exported_docs/ros2/ROS_2_Core_Maintainer_Guide\357\203\201.txt" new file mode 100644 index 0000000..2f8a014 --- /dev/null +++ "b/exported_docs/ros2/ROS_2_Core_Maintainer_Guide\357\203\201.txt" @@ -0,0 +1,50 @@ +Title: ROS 2 Core Maintainer Guide +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Core-maintainer-guide.html +Section: Installation +-------------------------------------------------------------------------------- + +ROS 2 Core Maintainer GuideEach package in the ROS 2 core has one or more maintainers that are responsibile for the general health of the package. +This guide gives some information about the responsibilities of a ROS 2 core package maintainer.Table of ContentsReviewsContinuous IntegrationPR builds (https://build.ros2.org/view/Rpr)CI builds (https://ci.ros2.org)Merging Pull RequestsKeeping CI greenMaking releasesSource releaseBinary releaseBackporting to released distributionsResponding to issuesGetting helpReviewsAll incoming code to ROS 2 core repositories must be reviewed. +The review is looking for:Suitability in the packageCorrect codeConforms to developer guidelines:Developer GuideCode Style GuideAdds tests for the bug/featureAdds documentation for new featuresClean Continuous Integration runTargets default branch (usually “rolling”)Has at least one approval from a maintainer that is not the authorContinuous IntegrationAll incoming code to ROS 2 core repositories must be run through Continuous Integration. +ROS 2 currently has two separate CI systems, and it is required that PRs pass both of them before merging.PR builds (https://build.ros2.org/view/Rpr)ROS 2 PR (Pull Request) builds run automatically every time a pull request is opened. +These builds run a build and test of this repository, and this repository only. +This means that it does not build any dependencies, and it also does not build any repositories that depend upon packages in this repository. +These builds are good for quick feedback to see if the change passes linters, unit tests, etc. +There are two major problems with them:These builds do not work across multiple repositories (so won’t work for adding or changing an API, etc)These tests only run on Linux (they won’t run on macOS or Windows)To address these two problems, there is also the CI builds.CI builds (https://ci.ros2.org)CI builds do not run automatically when a pull request is opened. +One of the maintainers of the repository must manually request that a CI build is done by going tohttps://ci.ros2.org/job/ci_launcher/.By default, running a job in this way will build and run tests for all packages (> 300 currently) on all platforms (Linux, macOS, and Windows). +As a full run can take many hours and tie up the CI machines, it is recommended that all runs here restrict the number of packages that are built and tested. +This can be accomplished by using the colcon arguments--packages-up-to,--packages-select,--packages-above-and-dependencies,--packages-above, amongst others. +See thecolcon documentationfor more examples on the flags that can be used. +Further documentation on how to use the CI machinery is available athttps://github.com/ros2/ci/blob/master/CI_BUILDERS.md.Merging Pull RequestsA pull request can be merged if all of the following are true:The DCO bot reports a passing resultThe PR build reports a passing resultThe CI build reports a passing result on all platformsThe code has been reviewed and approved by at least one maintainerAfter a PR is merged, it will automatically get built with the nextnightlies. +It is highly recommended to check the nightlies after merging pull requests to ensure no regressions have occurred.Keeping CI greenThe nightly jobs that run tests are typically much more comprehensive than what is done for individual pull requests. +For this reason, there can be regressions that occur in the nightlies that were not seen in the CI jobs. +It is a maintainer’s responsibility to check for regressions in their packages at the following locations:https://ci.ros2.org/view/nightlyhttps://ci.ros2.org/view/packaginghttps://build.ros2.org/view/Rcihttps://build.ros2.org/view/RdevFor any problems that are found, new issues and/or pull requests on the relevant repositories should be opened.Making releasesIn order to get new features and bugfixes out to end users, the maintainers must periodically do a release of the repository (a release may also be requested on-demand from other maintainers).As outlined in thedeveloper guide, ROS 2 packages follow semver for version numbers.A release, in ROS terms, consists of two distinct steps: making a source release, and then making a binary release.Source releaseA source release creates a changelog and a tag in the relevant repository.The process starts by generating or updating CHANGELOG.rst files with the following command:$catkin_generate_changelogIf one or more packages in the repository don’t have contain CHANGELOG.rst, add the--alloption to populate all of the previous commits for each package. +Thecatkin_generate_changelogcommand will simply populate the files with the commit logs from the repository. +Since those commit logs aren’t always appropriate for a changelog, it is recommended to edit CHANGELOG.rst and edit it to make it more readable. +Once editing is done, it is important to commit the updated CHANGELOG.rst file to the repository.The next step is to bump the version in the package.xml and the changelog files with the following command:$catkin_prepare_releaseThis command will find all of the packages in the repository, check that the changelogs exist, check that there are no uncommitted local changes, increment the version in the package.xml files, and commit/tag the changes with a bloom-compatible tag. +Using this command is the best way to ensure the release versions are consistent and compatible with bloom. +By default,catkin_prepare_releasewill bump the patch version of the packages, e.g. 0.1.1 -> 0.1.2 . +However, it can also bump the minor or major number, or even have an exact version set. +See the help output fromcatkin_prepare_releasefor more information.Assuming the above was successful, a source release has been made.Binary releaseThe next step is to use thebloom-releasecommand to create a binary release. +For full instructions on how to use bloom, please seehttp://wiki.ros.org/bloom. +To do a binary release of a repository, run:$bloom-release--track--rosdistroFor instance, to release therclcpprepository to the Jazzy distribution, the command would be:$bloom-release--trackjazzy--rosdistrojazzyrclcppThis command will fetch the release repository, make the necessary changes to make the release, push the changes to the release repository, and finally open a pull request tohttps://github.com/ros/rosdistro.Backporting to released distributionsAll incoming changes should first land on the development branch. +Once a change has been merged onto the development branch, it can be considered for backporting to released distributions. +However, any backported code must not breakAPIorABIin a released distribution. +If a change can be backported without breaking API or ABI, then a new pull request targeting the appropriate branch should be created. +The new pull request should be added to the appropriate distributions project board athttps://github.com/orgs/ros2/projects. +The new pull request should have all of the steps run as before, but making sure to target the distribution in question for CI, etc.Responding to issuesPackage maintainers should also look at incoming issues on the repository and triage the problems that users are having.For issues that look like questions, the issue should be closed and the user redirected toRobotics Stack Exchange.If an issue looks like a problem, but is not relevant to this particular repository, it should be moved to the appropriate repository with the GitHub “Transfer issue” button.If the reporter has not provided enough information to determine the cause of the problem, more information should be requested from the reporter.If this is a new feature, tag the issue with “help-wanted”.Any remaining issues should be reproduced, and determined if they are truly a bug. +If it is a bug, fixes are highly appreciated.Getting helpWhile doing maintenance on a package, questions about general procedures or individual issues may come up.For general questions, please follow thecontributing guidelines.For questions on individual issues, please tag the ROS 2 GitHub team (@ros/team), and someone on the team will take a look. + +Code Examples: + +Language: unknown +$catkin_generate_changelog + +Language: unknown +$catkin_prepare_release + +Language: unknown +$bloom-release--track--rosdistro + +Language: unknown +$bloom-release--trackjazzy--rosdistrojazzyrclcpp diff --git "a/exported_docs/ros2/ROS_2_Documentation\357\203\201.txt" "b/exported_docs/ros2/ROS_2_Documentation\357\203\201.txt" new file mode 100644 index 0000000..7dc4826 --- /dev/null +++ "b/exported_docs/ros2/ROS_2_Documentation\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: ROS 2 Documentation +URL: https://docs.ros.org/en/jazzy/index.html +Section: Installation +-------------------------------------------------------------------------------- + +ROS 2 DocumentationThe Robot Operating System (ROS) is a set of software libraries and tools for building robot applications.From drivers and state-of-the-art algorithms to powerful developer tools, ROS has the open source tools you need for your next robotics project.Since ROS was started in 2007, a lot has changed in the robotics and ROS community. +The goal of the ROS 2 project is to adapt to these changes, leveraging what is great about ROS 1 and improving what isn’t.Are you looking for documentation for a particular ROS package like MoveIt, image_proc, or octomap?Please seeROS Indexor check outthis index of per-package documentation.This site contains the documentation for ROS 2. +If you are looking for ROS 1 documentation, check out theROS wiki.If you use ROS 2 in your work, please seeCitationsto cite ROS 2.Getting startedInstallationInstructions to set up ROS 2 for the first timeTutorialsThe best place to start for new users!Hands-on sample projects that help you build a progression of necessary skillsHow-to GuidesQuick answers to your “How do I…?” questions without working through theTutorialsConceptsHigh-level explanations of core ROS 2 concepts covered in theTutorialsContactAnswers to your questions or a forum to start a discussionThe ROS 2 projectIf you’re interested in the advancement of the ROS 2 project:ContributingBest practices and methodology for contributing to ROS 2, as well as instructions for migrating existing ROS 1 content to ROS 2DistributionsPast, present and future ROS 2 distributionsFeatures StatusFeatures in the current releaseFeature IdeasIdeas for nice-to-have features that are not under active developmentRoadmapPlanned work for ROS 2 developmentROSCon TalksPresentations by the community on ROS 2Project GovernanceInformation about the ROS Technical Steering Committee, Working Groups, and upcoming eventsMarketingDownloadable marketing materialsInformation about the ROS trademarkROS community resourcesIf you need help, have an idea, or would like to contribute to the project, please visit our ROS community resources.Official ROS Discord Channel for discussion and support(ROS 1, ROS 2)Robotics Stack Exchange - community Q&A website(ROS 1, ROS 2)SeeContact Pagefor more informationROS Discourse(ROS 1, ROS 2)Forum for general discussions and announcements for the ROS communitySee theContact Pagefor more informationROS Index(ROS 1, ROS 2)Indexed list of all packages (i.e.Python Package Index (PyPI)for ROS packages)See which ROS distributions a package supportsLink to a package’s repository, API documentation, or websiteInspect a package’s license, build type, maintainers, status, and dependenciesGet more info for a package onRobotics Stack ExchangeROS resource status page(ROS 1, ROS 2)Check the current status of ROS resources like Discourse or the ROS build farm.General ROS project resourcesROS Enhancement Proposals (REPs)(ROS 1, ROS 2)Proposals for new designs and conventionsROS Robots(ROS 1, ROS 2)Showcases robots projects from the communityInstructions on how to contribute a robotROS Wiki(ROS 1)ROS 1 documentation and user modifiable contentActive until at least the last ROS 1 distribution is EOLROS.org(ROS 1, ROS 2)ROS 1 and ROS 2 product landing page, with high-level description of ROS and links to other ROS sitesEventsOfficial ROS Vimeo Channel(ROS 1, ROS 2)Videos of ROSCon Talks, community and working group meetings, and project demos.ROSCon website(ROS 1, ROS 2)ROSCon is our annual ROS developer conference.This page also lists regional ROS events like ROSConJP and ROSConFr.Open Source Robotics Foundation official events calendarThis calendar is for official OSRF Events and working group meetings.Submit your events here.Open Source Robotics Foundation community calendarThis calendar is for unofficial ROS community events.Submit your events here.MiscellaneousPurchase official ROS swagROS on social media@OpenRoboticsOrgand@ROSOrgon TwitterOpen Robotics on LinkedInVisit theOpen Source Robotics Foundation websiteTax deductible charitable donations to the Open Source Robotics Foundation can be sent viaDonorBox.DeprecatedROS 2 DesignEarly design decisions behind ROS 2 developmentNew design proposals should be submitted viaROS Enhancement Proposals (REPs) \ No newline at end of file diff --git "a/exported_docs/ros2/ROS_2_Security\357\203\201.txt" "b/exported_docs/ros2/ROS_2_Security\357\203\201.txt" new file mode 100644 index 0000000..1e6a463 --- /dev/null +++ "b/exported_docs/ros2/ROS_2_Security\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: ROS 2 Security +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Security.html +Section: Installation +-------------------------------------------------------------------------------- + +ROS 2 SecurityTable of ContentsOverviewThe Security EnclaveSecurity FilesEnclave IdentityEnclave PermissionsPrivate KeysSecurity Environment VariablesLearn MoreOverviewROS 2 includes the ability to secure communications among nodes within the ROS 2 computational graph. +Similar to discovery, security happens through the underlying ROS 2 middleware (provided it has support for the corresponding security plugins). +No additional software installation is needed to enable security; however, the middleware requires configuration files for each ROS graph participant. +These files enable encryption and authentication, and define policies both for individual nodes and for the overall ROS graph. +ROS 2 also adds a master “on/off” switch to control security behavior.ROS utilities can create the authoritativetrust anchorfor a ROS application, or an external certificate authority can be used.Built-in ROS 2 security features enable control over communications throughout the ROS graph. +This not only allows for encrypting data in transit between ROS domain participants, but also enables authentication of participants sending data, ensures the integrity of data being sent, and enables domain-wide access controls.ROS 2 security services are provided by the underlyingData Distribution Service (DDS)which is used for communications between nodes. +DDS vendors provide open source and commercial DDS implementations that work with ROS. +However, in order to create a specification-compliant implementation of DDS, all vendors must include security plugins as outlined in theDDS Security Specification. +ROS security features take advantage of these DDS security plugins to provide policy-based encryption, authentication and access control. +DDS and ROS security is enabled through predefined configuration files and environment variables.The Security EnclaveA security enclave encapsulates a single policy for protecting ROS communications. +The enclave may set policy for multiple nodes, for an entire ROS graph, or any combination of protected ROS processes and devices. +Security enclaves can be flexibly mapped to processes, users, or devices at deployment. +Adjusting this default behavior becomes important for optimizing communications and for complex systems. +See the ROS 2 Security Enclavesdesign documentfor additional details.Security FilesAROS 2 security enclaveis established with six files as outlined by the DDS specification. +Three of these files define an enclave’s identity, while three other files define the permissions to be granted to the enclave. +All six files reside in a single directory, and nodes launched without a qualified enclave path use files in the default root level enclave.Enclave IdentityThe Identity Certificate Authority fileidentity_ca.cert.pemacts as the trust anchor used to identify participants. +Each enclave also holds its unique identifying certificate in the filecert.pem, and the associated private key in the filekey.pem. +Because thecert.pemcertificate has been signed by identity certificate, when a participant presents this certificate to other domain members, they are able to validate the participant’s identity using their own copy of the identity certificate. +This valid certificate exchange allows the enclave to securely establish trusted communications with other participants. +The enclave does not not share thekey.pemprivate key, but only uses it for decryption and message signing.Enclave PermissionsThe Permissions Certificate Authority filepermissions_ca.cert.pemserves as the trust anchor to grant permissions to security enclaves. +This certificate is used to create the signed filegovernance.p7s, an XML document which defines domain-wide protection policies. +Similarly the XML filepermissions.p7soutlines permissions of this particular enclave and has been signed by the Permissions CA. +Domain members use a copy of the permissions CA to validate these signed files and grant the requested access.Although these two certificate authorities enable separate workflows for identity and permissions, often the same certificate serves as both the identity and the permissions authority.Private KeysThe identity and permissions certificates also have associated private key files. +Add new enclaves to the domain by signing their Certificate Signing Request (CSR) with the identity certificate’s private key. +Similarly, grant permissions for a new enclave by signing a permissions XML document with the permission certificate’s private key.Security Environment VariablesThe environment variableROS_SECURITY_ENABLEacts as the enclave’s master “on/off” switch for ROS 2 security features. +Security has been turned off by default, so security features will not be enabled even when the proper security files are present. +In order to enable ROS 2 security, set this environment variable totrue(case sensitive).Once security has been enabled, the environment variableROS_SECURITY_STRATEGYdefines how domain participants handle problems when launching participants. +Security features depend on certificates and properly signed configuration files, yet by default, an improperly configured participant will still launch successfully but without security features. +In order to enforce strict compliance with security settings and fail to launch non-compliant enclaves, set this environment variable toEnforce(case sensitive).Additional security-related environment variables can be found in theROS 2 DDS-Security Integration design document. +These variables generally assist ROS in managing enclaves and locating the security files.Learn MoreFor more information and hands-on exercises enabling ROS 2 communications security, see theSetting up security. \ No newline at end of file diff --git "a/exported_docs/ros2/ROS_2_developer_guide\357\203\201.txt" "b/exported_docs/ros2/ROS_2_developer_guide\357\203\201.txt" new file mode 100644 index 0000000..5443868 --- /dev/null +++ "b/exported_docs/ros2/ROS_2_developer_guide\357\203\201.txt" @@ -0,0 +1,158 @@ +Title: ROS 2 developer guide +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Contributing/Developer-Guide.html +Section: Installation +-------------------------------------------------------------------------------- + +ROS 2 developer guideTable of ContentsGeneral PrinciplesQuality PracticesVersioningChange control processDocumentationTestingGeneral PracticesIssuesBranchesPull requestsLibrary versioningDevelopment processChanges to RMW APITracking tasksPackage Naming ConventionsUnits of Measure and Coordinate System ConventionsProgramming conventionsFilesystem layoutUpstream PackagesDeveloper WorkflowArchitectural Development PracticesSoftware Development LifecycleBuild Farm IntroductionNote on Coverage runsHow to read the coverage rate from the buildfarm reportHow to calculate the coverage rate from the buildfarm reportHow to measure coverage locally using lcov (Ubuntu)This page defines the practices and policies we employ when developing ROS 2.General PrinciplesSome principles are common to all ROS 2 development:Shared ownership: +Everybody working on ROS 2 should feel ownership over all parts of the system. +The original author of a chunk of code does not have any special permission or obligation to control or maintain that chunk of code. +Everyone is free to propose changes anywhere, to handle any type of ticket, and to review any pull request.Be willing to work on anything: +As a corollary to shared ownership, everybody should be willing to take on any available task and contribute to any aspect of the system.Ask for help: +If you run into trouble on something, ask your fellow developers for help, via tickets, comments, or email, as appropriate.Quality PracticesPackages can ascribe to different levels of quality based on the development practices they adhere to, as per the guidelines inREP 2004: Package Quality Categories. +The categories are differentiated by their policies on versioning, testing, documentation, and more.The following sections are the specific development rules we follow to ensure core packages are of the highest quality (‘Level 1’). +We recommend all ROS developers strive to adhere to the following policies to ensure quality across the ROS ecosystem.For more specific code recommendations please seethe Quality Guide.VersioningWe will use theSemantic Versioning guidelines(semver) for versioning.We will also adhere to some ROS-specific rules built on top ofsemver'sfull meaning:Major version increments (i.e. breaking changes) should not be made within a released ROS distribution.Patch (interface-preserving) and minor (non-breaking) version increments do not break compatibility, so these sorts of changesareallowed within a release.Major ROS releases are the best time to release breaking changes. +If a core package needs multiple breaking changes, they should be merged into their integration branch (e.g. rolling) to allow catching problems in CI quickly, but released together to reduce the number of major releases for ROS users.Though major increments require a new distribution, a new distribution does not necessarily require a major bump (if development and release can happen without breaking API).For compiled code, the ABI is considered part of the public interface. +Any change that requires recompiling dependent code is considered major (breaking).ABI breaking changescanbe made in a minor version bumpbeforea distribution release (getting added to the rolling release).We enforce API stability for core packages in Dashing and Eloquent even though their major version components are0, despiteSemVer’s specificationregarding initial development.Subsequently, packages should strive to reach a mature state and increase to version1.0.0so to matchsemver'sspecifications.CaveatsThese rules arebest-effort. +In unlikely, extreme cases, it may be necessary to break API within a major version/distribution. +Whether an unplanned break increments the major or minor version will be assessed on a case-by-case basis.For example, consider a situation involving released X-turtle, corresponding to major version1.0.0, and released Y-turtle, corresponding to major version2.0.0.If an API-breaking fix is identified to be absolutely necessary in X-turtle, bumping to2.0.0is obviously not an option because2.0.0already exists.The solutions for handling X-turtle’s version in such a case, both non-ideal, are:Bumping X-turtle’s minor version: non-ideal because it violates SemVer’s principle that breaking changes must bump the major version.Bumping X-turtle’s major version past Y-turtle (to3.0.0): non-ideal because the older distro’s version would become higher than the already-available version of a newer distro, which would invalidate/break version-specific conditional code.The developer will have to decide which solution to use, or more importantly, which principle they are willing to break. +We cannot suggest one or the other, but in either case we do require that explicit measures be taken to communicate the disruption and its explanation to users manually (beyond just the version increment).If there were no Y-turtle, even though the fix would technically just be a patch, X-turtle would have to bump to2.0.0. +This case adheres to SemVer, but breaks from our own rule that major increments should not be introduced in a released distribution.This is why we consider the versioning rulesbest-effort. +As unlikely as the examples above are, it is important to accurately define our versioning system.Public API declarationAccording tosemver, every package must clearly declare a public API. +We will use the “Public API Declaration” section of the quality declaration of a package to declare what symbols are part of the public API.For most C and C++ packages the declaration is any header that it installs. +However, it is acceptable to define a set of symbols which are considered private. +Avoiding private symbols in headers can help with ABI stability, but is not required.For other languages like Python, a public API must be explicitly defined, so that it is clear what symbols can be relied on with respect to the versioning guidelines. +The public API can also be extended to build artifacts like configuration variables, CMake config files, etc. as well as executables and command-line options and output. +Any elements of the public API should be clearly stated in the package’s documentation. +If something you are using is not explicitly listed as part of the public API in the package’s documentation, then you cannot depend on it not changing between minor or patch versions.Deprecation strategyWhere possible, we will also use the tick-tock deprecation and migration strategy for major version increments. +New deprecations will come in a new distribution release, accompanied by compiler warnings expressing that the functionality is being deprecated. +In the next release, the functionality will be completely removed (no warnings).Example of functionfoodeprecated and replaced by functionbar:VersionAPIX-turtlevoid foo();Y-turtle[[deprecated(“use bar()”)]] void foo();
void bar();Z-turtlevoid bar();We must not add deprecations after a distribution is released. +Deprecations do not necessarily require a major version bump, though. +A deprecation can be introduced in a minor version bump if the bump happens before the distro is released (similar to ABI breaking changes).For example, if X-turtle begins development as2.0.0, a deprecation can be added in2.1.0before X-turtle is released.We will attempt to maintain compatibility across distros as much as possible. +However, like the caveats associated with SemVer, tick-tock or even deprecation in general may be impossible to completely adhere to in certain cases.Change control processAll changes must go through a pull request.We will enforce theDeveloper Certificate of Origin (DCO)on pull requests in ROSCore repositories.It requires all commit messages to contain theSigned-off-byline with an email address that matches the commit author.You can pass-s/--signoffto thegitcommitinvocation or write the expected message manually (e.g.Signed-off-by:YourNameDeveloper).DCO isnotrequired for pull requests that only address whitespace removal, typo correction, and othertrivial changes.Always run CI jobs for alltier 1 platformsfor every pull request and include links to jobs in the pull request. +(If you don’t have access to the Jenkins jobs someone will trigger the jobs for you.)A minimum of 1 approval from a fellow developer who did not author the pull request is required to consider it approved. +Approval is required before merging.Packages may choose to increase this number.Any required changes to documentation (API documentation, feature documentation, release notes, etc.) must be proposed before merging related changes.Guidelines for backporting PRsWhen changing an older version of ROS:Make sure the features or fixes are accepted and merged in the rolling branch before opening a PR to backport the changes to older versions.When backporting to older versions, also consider backporting to any otherstill supported versions, even non-LTS versions.If you are backporting a single PR in its entirety, title the backport PR “[Distro] ”. +If backporting a subset of changes from one or multiple PRs, the title should be “[Distro] ”.Link to all PRs whose changes you’re backporting from the description of your backport PR. +In a Dashing backport of a Foxy change, you do not need to link to the Eloquent backport of the same change.DocumentationAll packages should have these documentation elements present in their README or linked to from their README:Description and purposeDefinition and description of the public APIExamplesHow to build and install (should reference external tools/workflows)How to build and run testsHow to build documentationHow to develop (useful for describing things likepythonsetup.pydevelop)License and copyright statementsEach source file must have a license and copyright statement, checked with an automated linter.Each package must have a LICENSE file, typically the Apache 2.0 license, unless the package has an existing permissive license (e.g. rviz uses three-clause BSD).Each package should describe itself and its purpose assuming, as much as possible, that the reader has stumbled onto it without previous knowledge of ROS or other related projects.Each package should define and describe its public API so that there is a reasonable expectation for users about what is covered by the semantic versioning policy. +Even in C and C++, where the public API can be enforced by API and ABI checking, it is a good opportunity to describe the layout of the code and the function of each part of the code.It should be easy to take any package and from that package’s documentation understand how to build, run, build and run tests, and build the documentation. +Obviously we should avoid repeating ourselves for common workflows, like building a package in a workspace, but the basic workflows should be either described or referenced.Finally, it should include any documentation for developers. +This might include workflows for testing the code using something likepythonsetup.pydevelop, or it might mean describing how to make use of extension points provided by your package.Examples:capabilities:https://docs.ros.org/hydro/api/capabilities/html/This one gives an example of docs which describe the public APIcatkin_tools:https://catkin-tools.readthedocs.org/en/latest/development/extending_the_catkin_command.htmlThis is an example of describing an extension point for a packageAPI Documetation for ROS PackagesAPI documentation for all released ROS packages can befound here. +We recommend usingindex.ros.orgto search through available ROS packages to find their documentation.If you are a ROS package developer looking for guidance on documenting your package please seeour “how to” guide on package level documentation. +The documentation for all released ROS 2 packages is automatically hosted ondocs.ros.org.TestingAll packages should have some level ofsystem, integration, and/or unit tests.Unit testsshould always be in the package which is being tested and should make use of tools likeMockto try and test narrow parts of the codebase in constructed scenarios. +Unit tests should not bring in test dependencies that are not testing tools, e.g. gtest, nosetest, pytest, mock, etc…Integration testscan test interactions between parts of the code or between parts of the code and the system. +They often test software interfaces in ways that we expect the user to use them. +Like Unit tests, Integration tests should be in the package which is being tested and should not bring in non-tool test dependencies unless absolutely necessary, i.e. all non-tool dependencies should only be allowed under extreme scrutiny so they should be avoided if possible.System testsare designed to test end-to-end situations between packages and should be in their own packages to avoid bloating or coupling packages and to avoid circular dependencies.In general external or cross package test dependencies should be minimized to prevent circular dependencies and tightly coupled test packages.All packages should have some unit tests and possibly integration tests, but the degree to which they should have them is based on the package’s quality category. +The following subsections apply to ‘Level 1’ packages:Code coverageWe will provide line coverage, and achieve line coverage above 95%. +If a lower percentage target is justifiable, it must be prominently documented. +We may provide branch coverage, or exclude code from coverage (test code, debug code, etc.). +We require that coverage increase or stay the same before merging a change, but it may be acceptable to make a change that decreases code coverage with proper justification (e.g. deleting code that was previously covered can cause the percentage to drop).PerformanceWe strongly recommend performance tests, but recognize they don’t make sense for some packages. +If there are performance tests, we will choose to either check each change or before each release or both. +We will also require justification for merging a change or making a release that lowers performance.Linters and static analysisWe will useROS code styleand enforce it with linters fromament_lint_common. +All linters/static analysis that are part ofament_lint_commonmust be used.Theament_lint_autodocumentation provides information on runningament_lint_common.General PracticesSome practices are common to all ROS 2 development.These practices don’t affect package quality level as described inREP 2004, but are still highly recommended for the development process.IssuesWhen filing an issue please make sure to:Include enough information for another person to understand the issue. +In ROS 2, the following points are needed for narrowing down the cause of an issue. +Testing with as many alternatives in each category as feasible will be especially helpful.The operating system and version.Reasoning: ROS 2 supports multiple platforms, and some bugs are specific to particular versions of operating systems/compilers.The installation method.Reasoning: Some issues only manifest if ROS 2 has been installed from binary archives or from debs. +This can help us determine if the issue is with the packaging process.The specific version of ROS 2.Reasoning: Some bugs may be present in a particular ROS 2 release and later fixed. +It is important to know if your installation includes these fixes.The DDS/RMW implementation being used(seethis pagefor how to determine which one). +Reasoning: Communication issues may be specific to the underlying ROS middleware being used.The ROS 2 client library being used.Reasoning: This helps us narrow down the layer in the stack at which the issue might be.Include a list of steps to reproduce the issue.In case of a bug consider to provide ashort, self contained, correct (compilable), example. +Issues are much more likely to be resolved if others can reproduce them easily.Mention troubleshooting steps that have been tried already, including:Upgrading to the latest version of the code, which may include bug fixes that have not been released yet. +Seethis sectionand follow the instructions to get the “rolling” branches.Trying with a different RMW implementation. +Seethis pagefor how to do that.BranchesNoteThese are just guidelines. +It is up to the package maintainer to choose branch names that match their own workflow.It is good practice to haveseparate branchesin a package’s source repository for each ROS distribution it is targeting. +These branches are typically named after the distribution they target. +For example, ahumblebranch for development targeted specifically at the Humble distribution.Releases are also made from these branches, targeting the appropriate distribution. +Development targeted at a specific ROS distribution can happen on the appropriate branch. +For example: Development commits targetingfoxyare made to thefoxybranch, and package releases forfoxyare made from that same branch.NoteThis requires the package maintainers to perform backports or forwardports as appropriate to keep all branches up to date with features. +The maintainers must also perform general maintenance (bug fixes, etc.) on all branches from which package releases are still made.For example, if a feature is merged into the Rolling-specific branch (e.g.rollingormain), and that feature is also appropriate +to the Humble distribution (does not break API, etc.), then it is good practice to backport the feature to the Humble-specific branch.The maintainers may make releases for those older distributions if there are new features or bug fixes available.What aboutmainandrolling?maintypically targetsRolling(and so, the next unreleased ROS distribution), though the maintainers may decide to develop and release from arollingbranch instead.Pull requestsA pull request should only focus on one change. +Separate changes should go into separate pull requests. +SeeGitHub’s guide to writing the perfect pull request.A patch should be minimal in size and avoid any kind of unnecessary changes.A pull request must contain minimum number of meaningful commits.You can create new commits while the pull request is under review.Before merging a pull request all changes should be squashed into a small number of semantic commits to keep the history clear.But avoid squashing commits while a pull request is under review. +Your reviewers might not notice that you made the change, thereby introducing potential for confusion. +Plus, you’re going to squash before merging anyway; there’s no benefit to doing it early.Any developer is welcome to review and approve a pull request (seeGeneral Principles).When you are working on a change that is not ready for review or to be merged, use a draft pull request. +When that change is ready for review, move the pull request out of the draft state. +Note that if you want early feedback from specific people on a draft pull request, you can @ mention them in the pull request’s description or in a comment on the pull request.If your pull request depends on other pull requests, link to each depended on pull request by adding-Dependsonat the top of your pull request’s description. +Doing so helps reviewers understand the context of the pull request.When you start reviewing a pull request, comment on the pull request so that other developers know that you’re reviewing it.Pull-request review is not read-only, with the reviewer making comments and then waiting for the author to address them. +As a reviewer, feel free to make minor improvements (typos, style issues, etc.) in-place. +As the opener of a pull-request, if you are working in a fork, checking the box toallow edits from upstream contributorswill assist with the aforementioned. +As a reviewer, also feel free to make more substantial improvements, but consider putting them in a separate branch (either mention the new branch in a comment, or open another pull request from the new branch to the original branch).Any developer (the author, the reviewer, or somebody else) can merge any approved pull request.Library versioningWe will version all libraries within a package together. +This means that libraries inherit their version from the package. +This keeps library and package versions from diverging and shares reasoning with the policy of releasing packages which share a repository together. +If you need libraries to have different versions then consider splitting them into different packages.Development processThe default branch (in most cases the rolling branch) must always build, pass all tests and compile without warnings. +If at any time there is a regression it is the top priority to restore at least the previous state.Always build with tests enabled.Always run tests locally after changes and before proposing them in a pull request. +Besides using automated tests, also run the modified code path manually to ensure that the patch works as intended.Always run CI jobs for all platforms for every pull request and include links to the jobs in the pull request.For more details on recommended software development workflow, seeSoftware Development Lifecyclesection.Changes to RMW APIWhen updatingRMW API, it is required that RMW implementations for the Tier 1 middleware libraries are updated as well. +For example, a new functionrmw_foo()introduced to the RMW API must be implemented in the following packages (as of ROS Galactic):rmw_connextddsrmw_cycloneddsrmw_fastrtpsUpdates for non-Tier 1 middleware libraries should also be considered if feasible (e.g. depending on the size of the change). +SeeREP-2000for the list of middleware libraries and their tiers.Tracking tasksTo help organize work on ROS 2, the core ROS 2 development team uses kanban-styleGitHub project boards.Not all issues and pull requests are tracked on the project boards, however. +A board usually represents an upcoming release or specific project. +Tickets can be browsed on a per-repo basis by browsing theROS 2 repositories’individual issue pages.The names and purposes of columns in any given ROS 2 project board vary, but typically follow the same general structure:To do: +Issues that are relevant to the project, ready to be assignedIn progress: +Active pull requests on which work is currently in progressIn review: +Pull requests where work is complete and ready for review, and for those currently under active reviewDone: +Pull requests and related issues are merged/closed (for informational purposes)To request permission to make changes, simply comment on the tickets you’re interested in. +Depending on the complexity, it might be useful to describe how you plan to address it. +We will update the status (if you don’t have the permission) and you can start working on a pull request. +If you contribute regularly we will likely just grant you permission to manage the labels etc. yourself.Package Naming ConventionsNames play an important role in ROS and following naming conventions simplifies the process of learning and understanding large systems.The ROS packages occupy a flat namespace, so naming should be done carefully and consistently. There is a standard for package naming inREP-144Package names should follow common C variable naming conventions: lower case, start with a letter, use underscore separators, e.g. laser_viewerPackage names should be specific enough to identify what the package does. +For example, a motion planner is not called planner. +If it implements the wavefront propagation algorithm, it might be called wavefront_planner. +There’s obviously tension between making a name specific and keeping it from becoming overly verbose.Using catchall names such as utils should be avoided as they do not scope what goes into the package or what should be outside the package.To check whether a name is taken, consulthttps://index.ros.org/packages/. +If you’d like your repository included in that list, see therosdistro Contributing Guide.Our goal is to develop a canonical set of tools for making robots do interesting things. +The package name should tell you what the package does, not where it came from. +It should be possible for us, as a community, to make this work. +An Ubuntu distribution offers approximately 33,000 packages without inserting origin or authorship into names.Prefixing a package name is recommended only when the package is not meant to be used more widely (e.g., packages that are specific to the PR2 robot use thepr2_prefix). +You might prefix the package name when forking an existing package, but again, the prefix would hopefully communicate what changed, not who changed it.Prefixing a package name with ‘ros’ is redundant for a ROS package. +This is not recommended except for very core packages.Units of Measure and Coordinate System ConventionsStandard units and coordinate conventions for use in ROS have been formalized inREP-103. +All messages should follow these guidelines unless there’s a very strong reason which is very clearly documented to avoid confusion.Representation of special conditions within distance measurements like “too close” or “too far” in ROS have been formalized inREP-0117.Programming conventionsDefensive programming: ensure that assumptions are held as early as possible. +E.g. check every return code and make sure to at least throw an exception until the case is handled more gracefully.All error messages must be directed tostderr.Declare variables in the narrowest scope possible.Keep group of items (dependencies, imports, includes, etc.) ordered alphabetically.C++ specificAvoid using direct streaming (<<) tostdout/stderrto prevent interleaving between multiple threads.Avoid using references forstd::shared_ptrsince that subverts the reference counting. +If the original instance goes out of scope and the reference is being used it accesses freed memory.Filesystem layoutThe filesystem layout of packages and repositories should follow the same conventions in order to provide a consistent experience for users browsing our source code.Package layoutsrc: contains all C and C++ codeAlso contains C/C++ headers which are not installedinclude: contains all C and C++ headers which are installed: for all C and C++ installed headers they should be folder namespaced by the package name: contains all Python codetest: contains all automated tests and test dataconfig: contains configuration files, e.g. YAML parameters files and RViz config filesdoc: contains all the documentationlaunch: contains all launch filesmsg: contains all ROS Message definitionssrv: contains all ROS Service definitionsaction: contains all ROS Action definitionspackage.xml: as defined byREP-0140(may be updated for prototyping)CMakeLists.txt: only ROS packages which use CMakesetup.py: only ROS packages which use Python code onlyREADME: can be rendered on GitHub as a landing page for the projectThis can be as short or detailed as is convenient, but it should at least link to project documentationConsider putting a CI or code coverage tag in this READMEIt can also be.rstor anything else that GitHub supportsCONTRIBUTING: describes the contribution guidelinesThis might include license implication, e.g. when using the Apache 2 License.LICENSE: a copy of the license or licenses for this packageCHANGELOG.rst:REP-0132compliant changelogRepository layoutEach package should be in a subfolder which has the same name as the package. +If a repository contains only a single package it can optionally be in the root of the repository.Upstream PackagesPackages in Debian and Ubuntu UpstreamThanks to diligent effort from Jochen Sprickerhof and Leopold Palomo-Avellaneda, some of theROS 2 packages are now availablefrom the main Debian and Ubuntu repositories.Here is a short overview of the process from Jochen at ROSCon 2015. +The original ROS packages have been modified to follow Debian guidelines, which includes splitting packages into multiple pieces, changing names in some cases, installing to /usr according to FHS guidelines, and using soversions on shared libraries.In addition several of the bootstrap dependencies such as command line tools likevcstoolandcolconas well as some libraries likeosrf-pycommonandamentare also packaged upstream.Unlike the OSRF-provided ROS packages fromhttp://packages.ros.org, the packages in the upstream repositories are not attached to a specificROS distribution. +Rather, they represent a snapshot in time that will be updated periodically within Debian unstable and then latched at various points into downstream Debian and Ubuntu distributions.Don’t mix the streamsWe strongly recommend against mixing ROS packages from upstream Debian/Ubuntu and fromhttp://packages.ros.orgon the same system. +In some cases such a mixed system will work correctly, but there can be negative interactions between the two sets of packages. +We’re working with Jochen and friends to minimize the chance of problems via documentation and package conflict specifications, but we expect some risks to remain, including some fairly subtle issues.As such, we recommend that you choose to either install packages from upstream or fromhttp://packages.ros.org, but not both. +Not only should you not install packages from both at the same time, but if you intend to use the upstream packages then you should not even have thehttp://packages.ros.orgentries in your apt sources (i.e. in any files in/etc/apt/sources*). +Having both of them enabled can cause mixing of packages which overlap by name between the two sources, e.g.python3-rospkg.Known DifferencesAs compared to the ROS packages from packages.ros.org, there are some differences in the upstream ROS packages that people should be aware of:The package set is incomplete.Packages may have different names and be partitioned differently.Developer WorkflowWe track open tickets and active PRs related to upcoming releases and larger projects usingGitHub project boards.The usual workflow is:Discuss design (GitHub ticket on the appropriate repository, and a design PR tohttps://github.com/ros2/designif needed)Write implementation on a feature branch on a forkPlease check out thedeveloper guidefor guidelines and best practicesWrite testsEnable and run lintersRun tests locally usingcolcontest(see thecolcon tutorial)Once everything builds locally without warnings and all tests are passing, run CI on your feature branch:Go to ci.ros2.orgLog in (top right corner)Click on theci_launcherjobClick “Build with Parameters” (left column)In the first box “CI_BRANCH_TO_TEST” enter your feature branch nameHit thebuildbutton(if you are not a ROS 2 committer, you don’t have access to the CI farm. In that case, ping the reviewer of your PR to run CI for you)If your use case requires running code coverage:Go to ci.ros2.orgLog in (top right corner)Click on theci_linux_coveragejobClick “Build with Parameters” (left column)Be sure of leaving “CI_BUILD_ARGS” and “CI_TEST_ARGS” with the default valuesHit thebuildbuttonAt the end of the document there are instructions on how tointerpret the result of the reportandcalculate the coverage rateIf the CI job built without warnings, errors and test failures, post the links of your jobs on your PR or high-level ticket aggregating all your PRs (see examplehere)Note that the markdown for these badges is in the console output of theci_launcherjobWhen the PR has been approved:the person who submitted the PR merges it using “Squash and Merge” option so that we keep a clean historyIf the commits deserve to keep separated: squash all the nitpick/linters/typo ones together and merge the remaining setNote: each PR should target a specific feature so Squash and Merge should make sense 99% of the timeDelete the branch once mergedArchitectural Development PracticesThis section describes the ideal lifecycle that should be employed when making large architectural changes to ROS 2.Software Development LifecycleThis section describes step-by-step how to plan, design, and implement a new feature:Task CreationCreating the Design DocumentDesign ReviewImplementationCode ReviewTask creationTasks requiring changes to critical parts of ROS 2 should have design reviews during early stages of the release cycle. +If a design review is happening in the later stages, the changes will be part of a future release.An issue should be created in the appropriateros2 repository, clearly describing the task being worked on.It should have a clear success criteria and highlight the concrete improvements expected from it.If the feature is targeting a ROS release, ensure this is tracked in the ROS release ticket (example).Writing the design documentDesign docs must never include confidential information. +Whether or not a design document is required for your change depends on how big the task is.You are making a small change or fixing a bug:A design document is not required, but an issue should be opened in the appropriate repository to track the work and avoid duplication of efforts.You are implementing a new feature or would like to contribute to OSRF-owned infrastructure (like Jenkins CI):Design doc is required and should be contributed toros2/designto be made accessible onhttps://design.ros2.org/.You should fork the repository and submit a pull request detailing the design.Mention the related ros2 issue (for example,Designdocfortaskros2/ros2#) in the pull request or the commit message. +Detailed instructions are on theROS 2 Contributepage. +Design comments will be made directly on the pull request.If the task is planned to be released with a specific version of ROS, this information should be included in the pull request.Design document reviewOnce the design is ready for review, a pull request should be opened and appropriate reviewers should be assigned. +It is recommended to include project owner(s) - +maintainers of all impacted packages (as defined bypackage.xmlmaintainer field, seeREP-140) - as reviewers.If the design doc is complex or reviewers have conflicting schedules, an optional design review meeting can be set up. +In this case,Before the meetingSend a meeting invite at least one week in advanceMeeting duration of one hour is recommendedMeeting invite should list all decisions to be made during the review (decisions requiring package maintainer approval)Meeting required attendees: design pull request reviewersMeeting optional attendees: all OSRF engineers, if applicableDuring the meetingThe task owner drives the meeting, presents their ideas and manages discussions to ensure an agreement is reached on timeAfter the meetingThe task owner should send back meeting notes to all attendeesIf minor issues have been raised about the design:The task owner should update the design doc pull request based on the feedbackAdditional review is not requiredIf major issues have been raised about the design:It is acceptable to remove sections for which there is no clear agreementThe debatable parts of the design can be resubmitted as a separate task in the futureIf removing the debatable parts is not an option, work directly with package owners to reach an agreementOnce consensus is reached:Ensure theros2/designpull request has been merged, if applicableUpdate and close the GitHub issue associated with this design taskImplementationBefore starting, go through thePull requestssection for best practices.For each repo to be modified:Modify the code, go to the next step if finished or at regular intervals to backup your work.Self-reviewyour changes usinggitadd-i.Create a new signed commit usinggitcommit-s.A pull request should contain minimal semantically meaningful commits (for instance, a large number of 1-line commits is not acceptable). +Create new fixup commits while iterating on feedback, or optionally, amend existing commits usinggitcommit--amendif you don’t want to create a new commit every time.Each commit must have a properly written, meaningful, commit message. +More instructionshere.Moving files must be done in a separate commit, otherwise git may fail to accurately track the file history.Either the pull request description or the commit message must contain a reference to the related ros2 issue, so it gets automatically closed when the pull request is merged. +See thisdocfor more details.Push the new commits.Code reviewOnce the change is ready for code review:Open a pull request for each modified repository.Remember to followPull requestsbest practices.GitHubcan be used to create pull requests from the command-line.If the task is planned to be released with a specific version of ROS, this information should be included in each pull request.Package owners who reviewed the design document should be mentioned in the pull request.Code review SLO: although reviewing pull requests is best-effort, +it is helpful to have reviewers comment on pull requests within a week and +code authors to reply back to comments within a week, so there is no loss of context.Iterate on feedback as usual, amend and update the development branch as needed.Once the PR is approved, package maintainers will merge the changes in.Build Farm IntroductionThe build farm is located atci.ros2.org.Every night we run nightly jobs which build and run all the tests in various scenarios on various platforms. +Additionally, we test all pull requests against these platforms before merging.This is the current set of target platforms and architectures, though it evolves overtime:Ubuntu 24.04 Nobleamd64aarch64Windows 10amd64There are several categories of jobs on the buildfarm:manual jobs (triggered manually by developers):ci_linux: build + test the code on Ubuntuci_linux-aarch64: build + test the code on Ubuntu on an ARM 64-bit machine (aarch64)ci_linux_coverage: build + test + generation of test coverageci_windows: build + test the code on Windowsci_launcher: trigger all the jobs listed abovenightly (run every night):Debug: build + test the code with CMAKE_BUILD_TYPE=Debugnightly_linux_debugnightly_linux-aarch64_debugnightly_win_debRelease: build + test the code with CMAKE_BUILD_TYPE=Releasenightly_linux_releasenightly_linux-aarch64_releasenightly_win_relRepeated: build then run each test up to 20 times or until failed (aka flakiness hunter)nightly_linux_repeatednightly_linux-aarch64_repeatednightly_win_repCoverage:nightly_linux_coverage: build + test the code + analyses coverage for c/c++ and pythonresults are exported as a cobertura reportpackaging (run every night; result is bundled into an archive):packaging_linuxpackaging_windowsTwo additional build farms support the ROS / ROS 2 ecosystem by providing building of source and +binary packages, continuous integration, testing, and analysis.For details, frequently asked questions, and troubleshooting seebuild farms.Note on Coverage runsROS 2 packages are organized in a way that the testing code for a given package is not only contained within the package, but could also be present in a different package. +In other words: packages can exercise code belonging to other packages during the testing phase.To achieve the coverage rate reached by all code available in the ROS 2 core packages it is recommended to run builds using a fixed set of proposed repositories. +That set is defined in the default parameters of coverage jobs in Jenkins.How to read the coverage rate from the buildfarm reportTo see the coverage report for a given package:When theci_linux_coveragebuild finishes, click onCoverageReportScroll down to theCoverageBreakdownbyPackagetableIn the table, look at the first column called “Name”The coverage reports in the buildfarm include all the packages that were used in the ROS workspace. +The coverage report includes different paths corresponding to the same package:Name entries with the form:src.*...*These correspond to the unit test runs available in a package against its own source codeName entries with the form:build...*These correspond to the unit test runs available in a package against its files generated at building or configuring timeName entries with the form:install..*These correspond to the system/integration tests coming from testing runs of other packagesHow to calculate the coverage rate from the buildfarm reportGet the combined unit coverage rate using the automatic script:From the ci_linux_coverage Jenkins build copy the URL of the buildDownload theget_coverage_ros2_pkgscriptExecute the script:./get_coverage_ros2_pkg.py(README)Grab the results from the “Combined unit testing” final line in the output of the scriptAlternative: get the combined unit coverage rate from coverage report (require manual calculation):When the ci_linux_coverage build finishes, click onCoberturaCoverageReportScroll down to theCoverageBreakdownbyPackagetableIn the table, under the first column “Name”, look for (where is your package under testing):all the directories under the patternsrc.*...*grab the two absolute values in the column “Lines”.all the directories under the patternbuild/..*grab the two absolute values in the column “Lines”.With the previous selection: for each cell, the first value is the lines tested and the second is the total lines of code. +Aggregate all rows for getting the total of the lines tested and the total of lines of code under test. +Divide to get the coverage rate.How to measure coverage locally using lcov (Ubuntu)To measure coverage on your own machine, installlcov.sudoaptinstall-ylcovThe rest of this section assumes you are working from your colcon workspace. +Compile in debug with coverage flags. +Feel free to use colcon flags to target specific packages.colconbuild--cmake-args-DCMAKE_BUILD_TYPE=Debug-DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}--coverage"-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS}--coverage"lcovrequires an initial baseline, which you can produce with the following command. +Update the output file location for your needs.lcov--no-external--capture--initial--directory.--output-file~/ros2_base.infoRun tests for the packages that matter for your coverage measurements. +For example, if measuringrclcppalso withtest_rclcppcolcontest--packages-selectrclcpptest_rclcppCapture the lcov results with a similar command this time dropping the--initialflag.lcov--no-external--capture--directory.--output-file~/ros2.infoCombine the trace .info files:lcov--add-tracefile~/ros2_base.info--add-tracefile~/ros2.info--output-file~/ros2_coverage.infoGenerate html for easy visualization and annotation of covered lines.mkdir-pcoverage +genhtml~/ros2_coverage.info--output-directorycoverage + +Code Examples: + +Language: unknown +sudoaptinstall-ylcov + +Language: unknown +colconbuild--cmake-args-DCMAKE_BUILD_TYPE=Debug-DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}--coverage"-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS}--coverage" + +Language: unknown +lcov--no-external--capture--initial--directory.--output-file~/ros2_base.info + +Language: unknown +colcontest--packages-selectrclcpptest_rclcpp + +Language: unknown +lcov--no-external--capture--directory.--output-file~/ros2.info + +Language: unknown +lcov--add-tracefile~/ros2_base.info--add-tracefile~/ros2.info--output-file~/ros2_coverage.info + +Language: unknown +mkdir-pcoverage +genhtml~/ros2_coverage.info--output-directorycoverage diff --git "a/exported_docs/ros2/ROS_2_on_Raspberry_Pi\357\203\201.txt" "b/exported_docs/ros2/ROS_2_on_Raspberry_Pi\357\203\201.txt" new file mode 100644 index 0000000..c444941 --- /dev/null +++ "b/exported_docs/ros2/ROS_2_on_Raspberry_Pi\357\203\201.txt" @@ -0,0 +1,18 @@ +Title: ROS 2 on Raspberry Pi +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Installing-on-Raspberry-Pi.html +Section: Installation +-------------------------------------------------------------------------------- + +ROS 2 on Raspberry PiROS 2 is supported on both 32 bit (arm32) and 64 bit (arm64) ARM processors. +However, you can seeherethat arm64 receives Tier 1 support, while arm32 is Tier 3. +Tier 1 support means distribution specific packages and binary archives are available, while Tier 3 requires the user to compile ROS 2 from source.The fastest and simplest way to use ROS 2 is to use a Tier 1 supported configuration.This would mean either installing 64 bit Ubuntu on to the Raspberry Pi, or using the 64 bit version of Raspberry Pi OS and running ROS 2 in Docker.Ubuntu Linux on Raspberry Pi with binary ROS 2 installUbuntu for Raspberry Pi is availablehere.Make sure to confirm that you have selected the correct version as described inREP-2000.You can now install ROS 2 using the normal binary installation instructions for Ubuntu Linux.Raspberry Pi OS with ROS 2 in dockerRaspberry Pi OS 64 bit version isavailable here.Raspberry Pi OS is based on Debian which receives Tier 3 support, but it can run Ubuntu docker containers for Tier 1 support.After flashing the OS,install Docker.The official ROS 2 Docker images can be foundhere.You may choose from ros-core, ros-base, or perception. Seeherefor more information on these variants.Fetch and run an image:dockerpullros:jazzy-ros-core +dockerrun-it--rmros:jazzy-ros-coreYou can also build images yourself:Clone thedocker_images git repoonto the Raspberry Pi, change in to the directory linked above, then to the directory with your preferred variant.Inside of the directory, build the container with:dockerbuild-tros_docker.On a supported system it will only take a minute or two to build the docker containers, as the source code is already built in to binaries. + +Code Examples: + +Language: unknown +dockerpullros:jazzy-ros-core +dockerrun-it--rmros:jazzy-ros-core + +Language: unknown +dockerbuild-tros_docker. diff --git "a/exported_docs/ros2/RTI_Connext_DDS\357\203\201.txt" "b/exported_docs/ros2/RTI_Connext_DDS\357\203\201.txt" new file mode 100644 index 0000000..eca3322 --- /dev/null +++ "b/exported_docs/ros2/RTI_Connext_DDS\357\203\201.txt" @@ -0,0 +1,10 @@ +Title: RTI Connext DDS +URL: https://docs.ros.org/en/jazzy/Installation/DDS-Implementations/Install-Connext-University-Eval.html +Section: Installation +-------------------------------------------------------------------------------- + +RTI Connext DDSA libraries-only version of RTI Connext DDS 6.0.1 may be installed per theinstallation instructionsfor +Debian/Ubuntu Linux (amd64) platforms only, under anon-commercial license.A full-suite installation of RTI Connext DDS is available for many additional platforms, for universities, evaluation, or purchase. +This installation includes diagnostic tools, layered services, and security. See below for installation details.RTI University ProgramUniversity researchers and classroom users may be eligible for a free academic license through theRTI University Program. +This includes a one-year (renewable) license to the unabridged version of Connext DDS Secure, which includes diagnostic tools and layered services. +The university license application can be foundhere.RTI Connext DDS EvaluationTo install RTI Connext DDSversion 6.0.1Evalution:Visit theRTI Free Trial (6.0.1) site.Download the version(s) to match your environment.Contactlicense@rti.comfor an evaluation license.Install RTI Connext 6.0.1 by running the installation program. When finished, it will run the RTI Launcher.Use the RTI Launcher to install the license file (rti_license.dat) if needed. The launcher may also be used to launch the diagnostic tools and services. \ No newline at end of file diff --git "a/exported_docs/ros2/Reading_from_a_bag_file_(C++)\357\203\201.txt" "b/exported_docs/ros2/Reading_from_a_bag_file_(C++)\357\203\201.txt" new file mode 100644 index 0000000..22dcd66 --- /dev/null +++ "b/exported_docs/ros2/Reading_from_a_bag_file_(C++)\357\203\201.txt" @@ -0,0 +1,82 @@ +Title: Reading from a bag file (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Reading-From-A-Bag-File-CPP.html +Section: Installation +-------------------------------------------------------------------------------- + +Reading from a bag file (C++)Goal:Read data from a bag without using the CLI.Tutorial level:AdvancedTime:10 minutesContentsBackgroundPrerequisitesTasks1 Create a Package2 Write the C++ Reader3 Build and runSummaryBackgroundrosbag2doesn’t just provide theros2bagcommand line tool. +It also provides a C++ API for reading from and writing to a bag from your own source code. +This allows you to read the contents from a bag without having to play the bag, which can sometimes be useful.PrerequisitesYou should have therosbag2packages installed as part of your regular ROS 2 setup.If you need to install ROS 2, see theInstallation instructions.You should have already completed thebasic ROS 2 bag tutorial, and we will be using thesubsetbag you created there.Tasks1 Create a PackageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.In a new or existingworkspace, navigate to thesrcdirectory and create +a new package:ros2 pkg create --build-type ament_cmake --license Apache-2.0 bag_reading_cpp --dependencies rclcpp rosbag2_transport turtlesimYour terminal will return a message verifying the creation of your packagebag_reading_cppand all its necessary files and folders. +The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt. +In this case, the package will use therosbag2_transportpackage as well as therclcpppackage. +A dependency on theturtlesimpackage is also required for working with the custom turtlesim messages.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xmlorCMakeLists.txt. +As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.C++bagreadingtutorialYourNameApache-2.02 Write the C++ ReaderInside your package’ssrcdirectory, create a new file calledsimple_bag_reader.cppand paste the following code into it.#include#include#include#include#include#include"rclcpp/rclcpp.hpp"#include"rclcpp/serialization.hpp"#include"rosbag2_transport/reader_writer_factory.hpp"#include"turtlesim/msg/pose.hpp"usingnamespacestd::chrono_literals;classPlaybackNode:publicrclcpp::Node{public:PlaybackNode(conststd::string&bag_filename):Node("playback_node"){publisher_=this->create_publisher("/turtle1/pose",10);timer_=this->create_wall_timer(100ms,[this](){returnthis->timer_callback();});rosbag2_storage::StorageOptionsstorage_options;storage_options.uri=bag_filename;reader_=rosbag2_transport::ReaderWriterFactory::make_reader(storage_options);reader_->open(storage_options);}private:voidtimer_callback(){while(reader_->has_next()){rosbag2_storage::SerializedBagMessageSharedPtrmsg=reader_->read_next();if(msg->topic_name!="/turtle1/pose"){continue;}rclcpp::SerializedMessageserialized_msg(*msg->serialized_data);turtlesim::msg::Pose::SharedPtrros_msg=std::make_shared();serialization_.deserialize_message(&serialized_msg,ros_msg.get());publisher_->publish(*ros_msg);std::cout<<'('<x<<", "<y<<")\n";break;}}rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;rclcpp::Serializationserialization_;std::unique_ptrreader_;};intmain(intargc,char**argv){if(argc!=2){std::cerr<<"Usage: "<"<(argv[1]));rclcpp::shutdown();return0;}2.1 Examine the codeThe#includestatements at the top are the package dependencies. +Note the inclusion of headers from therosbag2_transportpackage for the functions and structures necessary to work with bag files.The next line creates the node which will read from the bag file and play back the data.classPlaybackNode:publicrclcpp::NodeNow, we can create a timer callback which will run at 10 hz. +Our goal is to replay one message to the/turtle1/posetopic each time the callback is run. +Note the constructor takes a path to the bag file as a parameter.public:PlaybackNode(conststd::string&bag_filename):Node("playback_node"){publisher_=this->create_publisher("/turtle1/pose",10);timer_=this->create_wall_timer(100ms,[this](){returnthis->timer_callback();});We also open the bag in the constructor. +Therosbag2_transport::ReaderWriterFactoryis a class that can construct a compressed or uncompressed reader or writer based on the storage options.rosbag2_storage::StorageOptionsstorage_options;storage_options.uri=bag_filename;reader_=rosbag2_transport::ReaderWriterFactory::make_reader(storage_options);reader_->open(storage_options);Now, inside our timer callback, we loop through messages in the bag until we read a message recorded from our desired topic. +Note that the serialized message has timestamp metadata in addition to the topic name.voidtimer_callback(){while(reader_->has_next()){rosbag2_storage::SerializedBagMessageSharedPtrmsg=reader_->read_next();if(msg->topic_name!="/turtle1/pose"){continue;}We then construct anrclcpp::SerializedMessageobject from the serialized data we just read. +Additionally, we need to create a ROS 2 deserialized message which will hold the result of our deserialization. +Then, we can pass both these objects to therclcpp::Serialization::deserialize_messagemethod.rclcpp::SerializedMessageserialized_msg(*msg->serialized_data);turtlesim::msg::Pose::SharedPtrros_msg=std::make_shared();serialization_.deserialize_message(&serialized_msg,ros_msg.get());Finally, we publish the deserialized message and print out the xy coordinate to the terminal. +We also break out of the loop so that we publish the next message during the next timer calback.publisher_->publish(*ros_msg);std::cout<<'('<x<<", "<y<<")\n";break;}We must also declare the private variables used throughout the node.rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;rclcpp::Serializationserialization_;std::unique_ptrreader_;};Lastly, we create the main function which will check that the user passes an argument for the bag file path and spins our node.intmain(intargc,char**argv){if(argc!=2){std::cerr<<"Usage: "<"<(argv[1]));rclcpp::shutdown();return0;}2.2 Add executableNow open theCMakeLists.txtfile.Below the dependencies block, which containsfind_package(rosbag2_transportREQUIRED), add the following lines of code.add_executable(simple_bag_reader src/simple_bag_reader.cpp)ament_target_dependencies(simple_bag_reader rclcpp rosbag2_transport turtlesim)install(TARGETSsimple_bag_readerDESTINATION lib/${PROJECT_NAME})3 Build and runNavigate back to the root of your workspace and build your new package.LinuxmacOSWindowscolcon build --packages-select bag_reading_cppcolcon build --packages-select bag_reading_cppcolcon build --merge-install --packages-select bag_reading_cppNext, source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.batNow, run the script. +Make sure to replace/path/to/subsetwith the path to yoursubsetbag.ros2 run bag_reading_cpp simple_bag_reader /path/to/subsetYou should see the (x, y) coordinates of the turtle printed to the console.SummaryYou created a C++ executable that reads data from a bag. +You then compiled and ran the executable which printed some information from the bag to the console. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 bag_reading_cpp --dependencies rclcpp rosbag2_transport turtlesim + +Language: unknown +C++bagreadingtutorialYourNameApache-2.0 + +Language: unknown +#include#include#include#include#include#include"rclcpp/rclcpp.hpp"#include"rclcpp/serialization.hpp"#include"rosbag2_transport/reader_writer_factory.hpp"#include"turtlesim/msg/pose.hpp"usingnamespacestd::chrono_literals;classPlaybackNode:publicrclcpp::Node{public:PlaybackNode(conststd::string&bag_filename):Node("playback_node"){publisher_=this->create_publisher("/turtle1/pose",10);timer_=this->create_wall_timer(100ms,[this](){returnthis->timer_callback();});rosbag2_storage::StorageOptionsstorage_options;storage_options.uri=bag_filename;reader_=rosbag2_transport::ReaderWriterFactory::make_reader(storage_options);reader_->open(storage_options);}private:voidtimer_callback(){while(reader_->has_next()){rosbag2_storage::SerializedBagMessageSharedPtrmsg=reader_->read_next();if(msg->topic_name!="/turtle1/pose"){continue;}rclcpp::SerializedMessageserialized_msg(*msg->serialized_data);turtlesim::msg::Pose::SharedPtrros_msg=std::make_shared();serialization_.deserialize_message(&serialized_msg,ros_msg.get());publisher_->publish(*ros_msg);std::cout<<'('<x<<", "<y<<")\n";break;}}rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;rclcpp::Serializationserialization_;std::unique_ptrreader_;};intmain(intargc,char**argv){if(argc!=2){std::cerr<<"Usage: "<"<(argv[1]));rclcpp::shutdown();return0;} + +Language: unknown +classPlaybackNode:publicrclcpp::Node + +Language: unknown +public:PlaybackNode(conststd::string&bag_filename):Node("playback_node"){publisher_=this->create_publisher("/turtle1/pose",10);timer_=this->create_wall_timer(100ms,[this](){returnthis->timer_callback();}); + +Language: unknown +rosbag2_storage::StorageOptionsstorage_options;storage_options.uri=bag_filename;reader_=rosbag2_transport::ReaderWriterFactory::make_reader(storage_options);reader_->open(storage_options); + +Language: unknown +voidtimer_callback(){while(reader_->has_next()){rosbag2_storage::SerializedBagMessageSharedPtrmsg=reader_->read_next();if(msg->topic_name!="/turtle1/pose"){continue;} + +Language: unknown +rclcpp::SerializedMessageserialized_msg(*msg->serialized_data);turtlesim::msg::Pose::SharedPtrros_msg=std::make_shared();serialization_.deserialize_message(&serialized_msg,ros_msg.get()); + +Language: unknown +publisher_->publish(*ros_msg);std::cout<<'('<x<<", "<y<<")\n";break;} + +Language: unknown +rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;rclcpp::Serializationserialization_;std::unique_ptrreader_;}; + +Language: unknown +intmain(intargc,char**argv){if(argc!=2){std::cerr<<"Usage: "<"<(argv[1]));rclcpp::shutdown();return0;} + +Language: unknown +add_executable(simple_bag_reader src/simple_bag_reader.cpp)ament_target_dependencies(simple_bag_reader rclcpp rosbag2_transport turtlesim)install(TARGETSsimple_bag_readerDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +colcon build --packages-select bag_reading_cpp + +Language: unknown +colcon build --packages-select bag_reading_cpp + +Language: unknown +colcon build --merge-install --packages-select bag_reading_cpp + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_reading_cpp simple_bag_reader /path/to/subset diff --git "a/exported_docs/ros2/Recording_a_bag_from_a_node_(C++)\357\203\201.txt" "b/exported_docs/ros2/Recording_a_bag_from_a_node_(C++)\357\203\201.txt" new file mode 100644 index 0000000..482e282 --- /dev/null +++ "b/exported_docs/ros2/Recording_a_bag_from_a_node_(C++)\357\203\201.txt" @@ -0,0 +1,206 @@ +Title: Recording a bag from a node (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Recording-A-Bag-From-Your-Own-Node-CPP.html +Section: Installation +-------------------------------------------------------------------------------- + +Recording a bag from a node (C++)Goal:Record data from your own C++ node to a bag.Tutorial level:AdvancedTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the C++ node3 Build and run4 Record synthetic data from a node5 Record synthetic data from an executableSummaryBackgroundrosbag2doesn’t just provide theros2bagcommand line tool. +It also provides a C++ API for reading from and writing to a bag from your own source code. +This allows you to subscribe to a topic and save the received data to a bag at the same time as performing any other processing of your choice on that data.PrerequisitesYou should have therosbag2packages installed as part of your regular ROS 2 setup.If you’ve installed from deb packages on Linux, it may be installed by default. +If it is not, you can install it using this command.sudo apt install ros-jazzy-rosbag2This tutorial discusses using ROS 2 bags, including from the terminal. +You should have already completed thebasic ROS 2 bag tutorial.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Navigate into theros2_wsdirectory created in aprevious tutorial. +Navigate into theros2_ws/srcdirectory and create a new package:ros2 pkg create --build-type ament_cmake --license Apache-2.0 bag_recorder_nodes --dependencies example_interfaces rclcpp rosbag2_cpp std_msgsYour terminal will return a message verifying the creation of your packagebag_recorder_nodesand all its necessary files and folders. +The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt. +In this case, the package will use therosbag2_cpppackage as well as therclcpppackage. +A dependency on theexample_interfacespackage is also required for later parts of this tutorial.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xmlorCMakeLists.txt. +As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.C++bagwritingtutorialYourNameApache-2.02 Write the C++ nodeInside theros2_ws/src/bag_recorder_nodes/srcdirectory, create a new file calledsimple_bag_recorder.cppand paste the following code into it.#include#include#includeclassSimpleBagRecorder:publicrclcpp::Node{public:SimpleBagRecorder():Node("simple_bag_recorder"){writer_=std::make_unique();writer_->open("my_bag");autosubscription_callback_lambda=[this](std::shared_ptrmsg){rclcpp::Timetime_stamp=this->now();writer_->write(msg,"chatter","std_msgs/msg/String",time_stamp);};subscription_=create_subscription("chatter",10,subscription_callback_lambda);}private:rclcpp::Subscription::SharedPtrsubscription_;std::unique_ptrwriter_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.1 Examine the codeThe#includestatements at the top are the package dependencies. +Note the inclusion of headers from therosbag2_cpppackage for the functions and structures necessary to work with bag files.In the class constructor we begin by creating the writer object we will use to write to the bag.writer_=std::make_unique();Now that we have a writer object, we can open the bag using it. +We specify just the URI of the bag to create, leaving other options at their defaults. +The default storage options are used, which means that anmcap-format bag will be created. +The default conversion options are used, too, which will perform no conversion, instead storing messages in the serialisation format they are received in.writer_->open("my_bag");With the writer now set up to record data we pass to it, we create a subscription and specify a callback for it. +We will write data to the bag in the callback.autosubscription_callback_lambda=[this](std::shared_ptrmsg){rclcpp::Timetime_stamp=this->now();writer_->write(msg,"chatter","std_msgs/msg/String",time_stamp);};subscription_=create_subscription("chatter",10,subscription_callback_lambda);The callback itself is different from a typical callback. +Rather than receiving an instance of the data type of the topic, we instead receive arclcpp::SerializedMessage. +We do this for two reasons.The message data will need to be serialized byrosbag2before being written to the bag, so rather than unserializing it when receiving the data and then re-serializing it, we ask ROS to just give us the serialized message as-is.The writer API can accept a serialized message.autosubscription_callback_lambda=[this](std::shared_ptrmsg){Within the subscription callback, the first thing to do is determine the time stamp to use for the stored message. +This can be anything appropriate to your data, but two common values are the time at which the data was produced, if known, and the time it is received. +The second option, the time of reception, is used here.rclcpp::Timetime_stamp=this->now();We can then write the message into the bag. +Because we have not yet registered any topics with the bag, we must specify the full topic information with the message. +This is why we pass in the topic name and the topic type.writer_->write(msg,"chatter","std_msgs/msg/String",time_stamp);The class contains two member variables.The subscription object.A managed pointer to the writer object used to write to the bag. +Note the type of writer used here is therosbag2_cpp::Writer, the generic writer interface. +Other writers may be available with different behaviours.rclcpp::Subscription::SharedPtrsubscription_;std::unique_ptrwriter_;The file finishes with themainfunction used to create an instance of the node and start ROS processing it.intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.2 Add executableNow open theCMakeLists.txtfile.Near the top of the file, changeCMAKE_CXX_STANDARDfrom14to17.#DefaulttoC++17if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 17)endif()Below the dependencies block, which containsfind_package(rosbag2_cppREQUIRED), add the following lines of code.add_executable(simple_bag_recorder src/simple_bag_recorder.cpp)ament_target_dependencies(simple_bag_recorder rclcpp rosbag2_cpp std_msgs)install(TARGETSsimple_bag_recorderDESTINATION lib/${PROJECT_NAME})3 Build and runNavigate back to the root of your workspace,ros2_ws, and build your new package.LinuxmacOSWindowscolcon build --packages-select bag_recorder_nodescolcon build --packages-select bag_recorder_nodescolcon build --merge-install --packages-select bag_recorder_nodesOpen a new terminal, navigate toros2_ws, and source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.batNow run the node:ros2 run bag_recorder_nodes simple_bag_recorderOpen a second terminal and run thetalkerexample node.ros2 run demo_nodes_cpp talkerThis will start publishing data on thechattertopic. +As the bag-writing node receives this data, it will write it to themy_bagbag.Terminate both nodes. +Then, in one terminal start thelistenerexample node.ros2 run demo_nodes_cpp listenerIn the other terminal, useros2bagto play the bag recorded by your node.ros2 bag play my_bagYou will see the messages from the bag being received by thelistenernode.If you wish to run the bag-writing node again, you will first need to delete themy_bagdirectory.4 Record synthetic data from a nodeAny data can be recorded into a bag, not just data received over a topic. +A common use case for writing to a bag from your own node is to generate and store synthetic data. +In this section you will learn how to write a node that generates some data and stores it in a bag. +We will demonstrate two approaches for doing this. +The first uses a node with a timer; this is the approach that you would use if your data generation is external to the node, such as reading data directly from hardware (e.g. a camera). +The second approach does not use a node; this is the approach you can use when you do not need to use any functionality from the ROS infrastructure.4.1 Write a C++ nodeInside theros2_ws/src/bag_recorder_nodes/srcdirectory, create a new file calleddata_generator_node.cppand paste the following code into it.#include#include#include#includeusingnamespacestd::chrono_literals;classDataGenerator:publicrclcpp::Node{public:DataGenerator():Node("data_generator"){data_.data=0;writer_=std::make_unique();writer_->open("timed_synthetic_bag");writer_->create_topic({0u,"synthetic","example_interfaces/msg/Int32",rmw_get_serialization_format(),{},"",});autotimer_callback_lambda=[this](){returnthis->timer_callback();};timer_=create_wall_timer(1s,timer_callback_lambda);}private:voidtimer_callback(){writer_->write(data_,"synthetic",now());++data_.data;}rclcpp::TimerBase::SharedPtrtimer_;std::unique_ptrwriter_;example_interfaces::msg::Int32data_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}4.2 Examine the codeMuch of this code is the same as the first example. +The important differences are described here.First, the name of the bag is changed.writer_->open("timed_synthetic_bag");In this example we are registering the topic with the bag in advance. +This is optional in most cases, but it must be done when passing in a serialized message without topic information.writer_->create_topic({0u,"synthetic","example_interfaces/msg/Int32",rmw_get_serialization_format(),{},"",});Rather than a subscription to a topic, this node has a timer. +The timer fires with a one-second period, and calls the given member function when it does.autotimer_callback_lambda=[this](){returnthis->timer_callback();};timer_=create_wall_timer(1s,timer_callback_lambda);Within the timer callback, we generate (or otherwise obtain, e.g. read from a serial port connected to some hardware) the data we wish to store in the bag. +The important difference between this and the previous sample is that the data is not yet serialized. +Instead we are passing a ROS message data type to the writer object, in this case an instance ofexample_interfaces/msg/Int32. +The writer will serialize the data for us before writing it into the bag.writer_->write(data_,"synthetic",now());4.3 Add executableOpen theCMakeLists.txtfile and add the following lines after the previously-added lines (specifically, after theinstall(TARGETS...)macro call).add_executable(data_generator_node src/data_generator_node.cpp)ament_target_dependencies(data_generator_node rclcpp rosbag2_cpp example_interfaces)install(TARGETSdata_generator_nodeDESTINATION lib/${PROJECT_NAME})4.4 Build and runNavigate back to the root of your workspace,ros2_ws, and build your package.LinuxmacOSWindowscolcon build --packages-select bag_recorder_nodescolcon build --packages-select bag_recorder_nodescolcon build --merge-install --packages-select bag_recorder_nodesOpen a new terminal, navigate toros2_ws, and source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.bat(If thetimed_synthetic_bagdirectory already exists, you must first delete it before running the node.)Now run the node:ros2 run bag_recorder_nodes data_generator_nodeWait for 30 seconds or so, then terminate the node withctrl-c. +Next, play back the created bag.ros2 bag play timed_synthetic_bagOpen a second terminal and echo the/synthetictopic.ros2 topic echo /syntheticYou will see the data that was generated and stored in the bag printed to the console at a rate of one message per second.5 Record synthetic data from an executableNow that you can create a bag that stores data from a source other than a topic, you will learn how to generate and record synthetic data from a non-node executable. +The advantage of this approach is simpler code and rapid creation of a large quantity of data.5.1 Write a C++ executableInside theros2_ws/src/bag_recorder_nodes/srcdirectory, create a new file calleddata_generator_executable.cppand paste the following code into it.#include#include// For rclcpp::Clock, rclcpp::Duration and rclcpp::Time#include#include#include#includeusingnamespacestd::chrono_literals;intmain(int,char**){example_interfaces::msg::Int32data;data.data=0;std::unique_ptrwriter_=std::make_unique();writer_->open("big_synthetic_bag");writer_->create_topic({0u,"synthetic","example_interfaces/msg/Int32",rmw_get_serialization_format(),{},"",});rclcpp::Clockclock;rclcpp::Timetime_stamp=clock.now();for(int32_tii=0;ii<100;++ii){writer_->write(data,"synthetic",time_stamp);++data.data;time_stamp+=rclcpp::Duration(1s);}return0;}5.2 Examine the codeA comparison of this sample and the previous sample will reveal that they are not that different. +The only significant difference is the use of a for loop to drive the data generation rather than a timer.Notice that we are also now generating time stamps for the data rather than relying on the current system time for each sample. +The time stamp can be any value you need it to be. +The data will be played back at the rate given by these time stamps, so this is a useful way to control the default playback speed of the samples. +Notice also that while the gap between each sample is a full second in time, this executable does not need to wait a second between each sample. +This allows us to generate a lot of data covering a wide span of time in much less time than playback will take.rclcpp::Clockclock;rclcpp::Timetime_stamp=clock.now();for(int32_tii=0;ii<100;++ii){writer_->write(data,"synthetic",time_stamp);++data.data;time_stamp+=rclcpp::Duration(1s);}5.3 Add executableOpen theCMakeLists.txtfile and add the following lines after the previously-added lines.add_executable(data_generator_executable src/data_generator_executable.cpp)ament_target_dependencies(data_generator_executable rclcpp rosbag2_cpp example_interfaces)install(TARGETSdata_generator_executableDESTINATION lib/${PROJECT_NAME})5.4 Build and runNavigate back to the root of your workspace,ros2_ws, and build your package.LinuxmacOSWindowscolcon build --packages-select bag_recorder_nodescolcon build --packages-select bag_recorder_nodescolcon build --merge-install --packages-select bag_recorder_nodesOpen a terminal, navigate toros2_ws, and source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.bat(If thebig_synthetic_bagdirectory already exists, you must first delete it before running the executable.)Now run the executable:ros2 run bag_recorder_nodes data_generator_executableNote that the executable runs and finishes very quickly.Now play back the created bag.ros2 bag play big_synthetic_bagOpen a second terminal and echo the/synthetictopic.ros2 topic echo /syntheticYou will see the data that was generated and stored in the bag printed to the console at a rate of one message per second. +Even though the bag was generated rapidly it is still played back at the rate the time stamps indicate.SummaryYou created a node that records data it receives on a topic into a bag. +You tested recording a bag using the node, and verified the data was recorded by playing back the bag. +You then went on to create a node and an executable to generate synthetic data and store it in a bag. + +Code Examples: + +Language: unknown +sudo apt install ros-jazzy-rosbag2 + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 bag_recorder_nodes --dependencies example_interfaces rclcpp rosbag2_cpp std_msgs + +Language: unknown +C++bagwritingtutorialYourNameApache-2.0 + +Language: unknown +#include#include#includeclassSimpleBagRecorder:publicrclcpp::Node{public:SimpleBagRecorder():Node("simple_bag_recorder"){writer_=std::make_unique();writer_->open("my_bag");autosubscription_callback_lambda=[this](std::shared_ptrmsg){rclcpp::Timetime_stamp=this->now();writer_->write(msg,"chatter","std_msgs/msg/String",time_stamp);};subscription_=create_subscription("chatter",10,subscription_callback_lambda);}private:rclcpp::Subscription::SharedPtrsubscription_;std::unique_ptrwriter_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +writer_=std::make_unique(); + +Language: unknown +writer_->open("my_bag"); + +Language: unknown +autosubscription_callback_lambda=[this](std::shared_ptrmsg){rclcpp::Timetime_stamp=this->now();writer_->write(msg,"chatter","std_msgs/msg/String",time_stamp);};subscription_=create_subscription("chatter",10,subscription_callback_lambda); + +Language: unknown +autosubscription_callback_lambda=[this](std::shared_ptrmsg){ + +Language: unknown +rclcpp::Timetime_stamp=this->now(); + +Language: unknown +writer_->write(msg,"chatter","std_msgs/msg/String",time_stamp); + +Language: unknown +rclcpp::Subscription::SharedPtrsubscription_;std::unique_ptrwriter_; + +Language: unknown +intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +#DefaulttoC++17if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 17)endif() + +Language: unknown +add_executable(simple_bag_recorder src/simple_bag_recorder.cpp)ament_target_dependencies(simple_bag_recorder rclcpp rosbag2_cpp std_msgs)install(TARGETSsimple_bag_recorderDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +colcon build --packages-select bag_recorder_nodes + +Language: unknown +colcon build --packages-select bag_recorder_nodes + +Language: unknown +colcon build --merge-install --packages-select bag_recorder_nodes + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_recorder_nodes simple_bag_recorder + +Language: unknown +ros2 run demo_nodes_cpp talker + +Language: unknown +ros2 run demo_nodes_cpp listener + +Language: unknown +ros2 bag play my_bag + +Language: unknown +#include#include#include#includeusingnamespacestd::chrono_literals;classDataGenerator:publicrclcpp::Node{public:DataGenerator():Node("data_generator"){data_.data=0;writer_=std::make_unique();writer_->open("timed_synthetic_bag");writer_->create_topic({0u,"synthetic","example_interfaces/msg/Int32",rmw_get_serialization_format(),{},"",});autotimer_callback_lambda=[this](){returnthis->timer_callback();};timer_=create_wall_timer(1s,timer_callback_lambda);}private:voidtimer_callback(){writer_->write(data_,"synthetic",now());++data_.data;}rclcpp::TimerBase::SharedPtrtimer_;std::unique_ptrwriter_;example_interfaces::msg::Int32data_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +writer_->open("timed_synthetic_bag"); + +Language: unknown +writer_->create_topic({0u,"synthetic","example_interfaces/msg/Int32",rmw_get_serialization_format(),{},"",}); + +Language: unknown +autotimer_callback_lambda=[this](){returnthis->timer_callback();};timer_=create_wall_timer(1s,timer_callback_lambda); + +Language: unknown +writer_->write(data_,"synthetic",now()); + +Language: unknown +add_executable(data_generator_node src/data_generator_node.cpp)ament_target_dependencies(data_generator_node rclcpp rosbag2_cpp example_interfaces)install(TARGETSdata_generator_nodeDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +colcon build --packages-select bag_recorder_nodes + +Language: unknown +colcon build --packages-select bag_recorder_nodes + +Language: unknown +colcon build --merge-install --packages-select bag_recorder_nodes + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_recorder_nodes data_generator_node + +Language: unknown +ros2 bag play timed_synthetic_bag + +Language: unknown +ros2 topic echo /synthetic + +Language: unknown +#include#include// For rclcpp::Clock, rclcpp::Duration and rclcpp::Time#include#include#include#includeusingnamespacestd::chrono_literals;intmain(int,char**){example_interfaces::msg::Int32data;data.data=0;std::unique_ptrwriter_=std::make_unique();writer_->open("big_synthetic_bag");writer_->create_topic({0u,"synthetic","example_interfaces/msg/Int32",rmw_get_serialization_format(),{},"",});rclcpp::Clockclock;rclcpp::Timetime_stamp=clock.now();for(int32_tii=0;ii<100;++ii){writer_->write(data,"synthetic",time_stamp);++data.data;time_stamp+=rclcpp::Duration(1s);}return0;} + +Language: unknown +rclcpp::Clockclock;rclcpp::Timetime_stamp=clock.now();for(int32_tii=0;ii<100;++ii){writer_->write(data,"synthetic",time_stamp);++data.data;time_stamp+=rclcpp::Duration(1s);} + +Language: unknown +add_executable(data_generator_executable src/data_generator_executable.cpp)ament_target_dependencies(data_generator_executable rclcpp rosbag2_cpp example_interfaces)install(TARGETSdata_generator_executableDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +colcon build --packages-select bag_recorder_nodes + +Language: unknown +colcon build --packages-select bag_recorder_nodes + +Language: unknown +colcon build --merge-install --packages-select bag_recorder_nodes + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_recorder_nodes data_generator_executable + +Language: unknown +ros2 bag play big_synthetic_bag + +Language: unknown +ros2 topic echo /synthetic diff --git "a/exported_docs/ros2/Recording_a_bag_from_a_node_(Python)\357\203\201.txt" "b/exported_docs/ros2/Recording_a_bag_from_a_node_(Python)\357\203\201.txt" new file mode 100644 index 0000000..7829ba5 --- /dev/null +++ "b/exported_docs/ros2/Recording_a_bag_from_a_node_(Python)\357\203\201.txt" @@ -0,0 +1,201 @@ +Title: Recording a bag from a node (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Recording-A-Bag-From-Your-Own-Node-Py.html +Section: Installation +-------------------------------------------------------------------------------- + +Recording a bag from a node (Python)Goal:Record data from your own Python node to a bag.Tutorial level:AdvancedTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the Python node3 Build and run4 Record synthetic data from a node5 Record synthetic data from an executableSummaryBackgroundrosbag2doesn’t just provide theros2bagcommand line tool. +It also provides a Python API for reading from and writing to a bag from your own source code. +This allows you to subscribe to a topic and save the received data to a bag at the same time as performing any other processing of your choice on that data. +You may do this, for example, to save data from a topic and the result of processing that data without needing to send the processed data over a topic just to record it. +Because any data can be recorded in a bag, it is also possible to save data generated by another source than a topic, such as synthetic data for training sets. +This is useful, for example, for quickly generating a bag that contains a large number of samples spread over a long playback time.PrerequisitesYou should have therosbag2packages installed as part of your regular ROS 2 setup.If you’ve installed from deb packages on Linux, it may be installed by default. +If it is not, you can install it using this command.sudo apt install ros-jazzy-rosbag2This tutorial discusses using ROS 2 bags, including from the terminal. +You should have already completed thebasic ROS 2 bag tutorial.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Followthese instructionsto create a new workspace namedros2_ws.Navigate into theros2_ws/srcdirectory and create a new package:ros2 pkg create --build-type ament_python --license Apache-2.0 bag_recorder_nodes_py --dependencies rclpy rosbag2_py example_interfaces std_msgsYour terminal will return a message verifying the creation of your packagebag_recorder_nodes_pyand all its necessary files and folders. +The--dependenciesargument will automatically add the necessary dependency lines to thepackage.xml. +In this case, the package will use therosbag2_pypackage as well as therclpypackage. +A dependency on theexample_interfacespackage is also required for message definitions.1.1 Updatepackage.xmlandsetup.pyBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xml. +As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.PythonbagwritingtutorialYourNameApache-2.0Also be sure to add this information to thesetup.pyfile as well.maintainer='Your Name',maintainer_email='you@email.com',description='Python bag writing tutorial',license='Apache-2.0',2 Write the Python nodeInside theros2_ws/src/bag_recorder_nodes_py/bag_recorder_nodes_pydirectory, create a new file calledsimple_bag_recorder.pyand paste the following code into it.importrclpyfromrclpy.nodeimportNodefromrclpy.serializationimportserialize_messagefromstd_msgs.msgimportStringimportrosbag2_pyclassSimpleBagRecorder(Node):def__init__(self):super().__init__('simple_bag_recorder')self.writer=rosbag2_py.SequentialWriter()storage_options=rosbag2_py._storage.StorageOptions(uri='my_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')self.writer.open(storage_options,converter_options)topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='chatter',type='std_msgs/msg/String',serialization_format='cdr')self.writer.create_topic(topic_info)self.subscription=self.create_subscription(String,'chatter',self.topic_callback,10)self.subscriptiondeftopic_callback(self,msg):self.writer.write('chatter',serialize_message(msg),self.get_clock().now().nanoseconds)defmain(args=None):rclpy.init(args=args)sbr=SimpleBagRecorder()rclpy.spin(sbr)rclpy.shutdown()if__name__=='__main__':main()2.1 Examine the codeTheimportstatements at the top are the package dependencies. +Note the importation of therosbag2_pypackage for the functions and structures necessary to work with bag files.In the class constructor, we begin by creating the writer object that we will use to write to the bag. +We are creating aSequentialWriter, which writes messages into the bag in the order they are received. +Other writers with different behaviours may be available inrosbag2.self.writer=rosbag2_py.SequentialWriter()Now that we have a writer object, we can open the bag using it. +We specify the URI of the bag to create and the format (mcap), leaving other options at their defaults. +The default conversion options are used, which will perform no conversion and store the messages in the serialization format they are received in.storage_options=rosbag2_py._storage.StorageOptions(uri='my_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')self.writer.open(storage_options,converter_options)Next, we need to tell the writer about the topics we wish to store. +This is done by creating aTopicMetadataobject and registering it with the writer. +This object specifies the topic name, topic data type, and serialization format used.topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='chatter',type='std_msgs/msg/String',serialization_format='cdr')self.writer.create_topic(topic_info)With the writer now set up to record data we pass to it, we create a subscription and specify a callback for it. +We will write data to the bag in the callback.self.subscription=self.create_subscription(String,'chatter',self.topic_callback,10)self.subscriptionThe callback receives the message in unserialized form (as is standard for therclpyAPI) and passes the message to the writer, specifying the topic that the data is for and the timestamp to record with the message. +However, the writer requires serialized messages to store in the bag. +This means that we need to serialize the data before passing it to the writer. +For this reason, we callserialize_message()and pass the result of that to the writer, rather than passing in the message directly.deftopic_callback(self,msg):self.writer.write('chatter',serialize_message(msg),self.get_clock().now().nanoseconds)The file finishes with themainfunction used to create an instance of the node and start ROS processing it.defmain(args=None):rclpy.init(args=args)sbr=SimpleBagRecorder()rclpy.spin(sbr)rclpy.shutdown()2.2 Add entry pointOpen thesetup.pyfile in thebag_recorder_nodes_pypackage and add an entry point for your node.entry_points={'console_scripts':['simple_bag_recorder = bag_recorder_nodes_py.simple_bag_recorder:main',],},3 Build and runNavigate back to the root of your workspace,ros2_ws, and build your new package.LinuxmacOSWindowscolcon build --packages-select bag_recorder_nodes_pycolcon build --packages-select bag_recorder_nodes_pycolcon build --merge-install --packages-select bag_recorder_nodes_pyOpen a new terminal, navigate toros2_ws, and source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.batNow run the node:ros2 run bag_recorder_nodes_py simple_bag_recorderOpen a second terminal and run thetalkerexample node.ros2 run demo_nodes_cpp talkerThis will start publishing data on thechattertopic. +As the bag-writing node receives this data, it will write it to themy_bagbag. +If themy_bagdirectory already exists, you must first delete it before running thesimple_bag_recordernode. +This is becauserosbag2will not overwrite existing bags by default, and so the destination directory cannot exist.Terminate both nodes. +Then, in one terminal start thelistenerexample node.ros2 run demo_nodes_cpp listenerIn the other terminal, useros2bagto play the bag recorded by your node.ros2 bag play my_bagYou will see the messages from the bag being received by thelistenernode.If you wish to run the bag-writing node again, you will first need to delete themy_bagdirectory.4 Record synthetic data from a nodeAny data can be recorded into a bag, not just data received over a topic. +A common use case for writing to a bag from your own node is to generate and store synthetic data. +In this section you will learn how to write a node that generates some data and stores it in a bag. +We will demonstrate two approaches for doing this. +The first uses a node with a timer; this is the approach that you would use if your data generation is external to the node, such as reading data directly from hardware (e.g. a camera). +The second approach does not use a node; this is the approach you can use when you do not need to use any functionality from the ROS infrastructure.4.1 Write a Python nodeInside theros2_ws/src/bag_recorder_nodes_py/bag_recorder_nodes_pydirectory, create a new file calleddata_generator_node.pyand paste the following code into it.importrclpyfromrclpy.nodeimportNodefromrclpy.serializationimportserialize_messagefromexample_interfaces.msgimportInt32importrosbag2_pyclassDataGeneratorNode(Node):def__init__(self):super().__init__('data_generator_node')self.data=Int32()self.data.data=0self.writer=rosbag2_py.SequentialWriter()storage_options=rosbag2_py._storage.StorageOptions(uri='timed_synthetic_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')self.writer.open(storage_options,converter_options)topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='synthetic',type='example_interfaces/msg/Int32',serialization_format='cdr')self.writer.create_topic(topic_info)self.timer=self.create_timer(1,self.timer_callback)deftimer_callback(self):self.writer.write('synthetic',serialize_message(self.data),self.get_clock().now().nanoseconds)self.data.data+=1defmain(args=None):rclpy.init(args=args)dgn=DataGeneratorNode()rclpy.spin(dgn)rclpy.shutdown()if__name__=='__main__':main()4.2 Examine the codeMuch of this code is the same as the first example. +The important differences are described here.First, the name of the bag is changed.storage_options=rosbag2_py._storage.StorageOptions(uri='timed_synthetic_bag',storage_id='mcap')The name of the topic is also changed, as is the data type stored.topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='synthetic',type='example_interfaces/msg/Int32',serialization_format='cdr')self.writer.create_topic(topic_info)Rather than a subscription to a topic, this node has a timer. +The timer fires with a one-second period, and calls the given member function when it does.self.timer=self.create_timer(1,self.timer_callback)Within the timer callback, we generate (or otherwise obtain, e.g. read from a serial port connected to some hardware) the data we wish to store in the bag. +As with the previous example, the data is not yet serialized, so we must serialize it before passing it to the writer.self.writer.write('synthetic',serialize_message(self.data),self.get_clock().now().nanoseconds)4.3 Add executableOpen thesetup.pyfile in thebag_recorder_nodes_pypackage and add an entry point for your node.entry_points={'console_scripts':['simple_bag_recorder = bag_recorder_nodes_py.simple_bag_recorder:main','data_generator_node = bag_recorder_nodes_py.data_generator_node:main',],},4.4 Build and runNavigate back to the root of your workspace,ros2_ws, and build your package.LinuxmacOSWindowscolcon build --packages-select bag_recorder_nodes_pycolcon build --packages-select bag_recorder_nodes_pycolcon build --merge-install --packages-select bag_recorder_nodes_pyOpen a new terminal, navigate toros2_ws, and source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.batIf thetimed_synthetic_bagdirectory already exists, you must first delete it before running the node.Now run the node:ros2 run bag_recorder_nodes_py data_generator_nodeWait for 30 seconds or so, then terminate the node withctrl-c. +Next, play back the created bag.ros2 bag play timed_synthetic_bagOpen a second terminal and echo the/synthetictopic.ros2 topic echo /syntheticYou will see the data that was generated and stored in the bag printed to the console at a rate of one message per second.5 Record synthetic data from an executableNow that you can create a bag that stores data from a source other than a topic, you will learn how to generate and record synthetic data from a non-node executable. +The advantage of this approach is simpler code and rapid creation of a large quantity of data.5.1 Write a Python executableInside theros2_ws/src/bag_recorder_nodes_py/bag_recorder_nodes_pydirectory, create a new file calleddata_generator_executable.pyand paste the following code into it.fromrclpy.clockimportClockfromrclpy.durationimportDurationfromrclpy.serializationimportserialize_messagefromexample_interfaces.msgimportInt32importrosbag2_pydefmain(args=None):writer=rosbag2_py.SequentialWriter()storage_options=rosbag2_py._storage.StorageOptions(uri='big_synthetic_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')writer.open(storage_options,converter_options)topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='synthetic',type='example_interfaces/msg/Int32',serialization_format='cdr')writer.create_topic(topic_info)time_stamp=Clock().now()foriiinrange(0,100):data=Int32()data.data=iiwriter.write('synthetic',serialize_message(data),time_stamp.nanoseconds)time_stamp+=Duration(seconds=1)if__name__=='__main__':main()5.2 Examine the codeA comparison of this sample and the previous sample will reveal that they are not that different. +The only significant difference is the use of a for loop to drive the data generation rather than a timer.Notice that we are also now generating time stamps for the data rather than relying on the current system time for each sample. +The time stamp can be any value you need it to be. +The data will be played back at the rate given by these time stamps, so this is a useful way to control the default playback speed of the samples. +Notice also that while the gap between each sample is a full second in time, this executable does not need to wait a second between each sample. +This allows us to generate a lot of data covering a wide span of time in much less time than playback will take.time_stamp=Clock().now()foriiinrange(0,100):data=Int32()data.data=iiwriter.write('synthetic',serialize_message(data),time_stamp.nanoseconds)time_stamp+=Duration(seconds=1)5.3 Add executableOpen thesetup.pyfile in thebag_recorder_nodes_pypackage and add an entry point for your node.entry_points={'console_scripts':['simple_bag_recorder = bag_recorder_nodes_py.simple_bag_recorder:main','data_generator_node = bag_recorder_nodes_py.data_generator_node:main','data_generator_executable = bag_recorder_nodes_py.data_generator_executable:main',],},5.4 Build and runNavigate back to the root of your workspace,ros2_ws, and build your package.LinuxmacOSWindowscolcon build --packages-select bag_recorder_nodes_pycolcon build --packages-select bag_recorder_nodes_pycolcon build --merge-install --packages-select bag_recorder_nodes_pyOpen a terminal, navigate toros2_ws, and source the setup files.LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.batIf thebig_synthetic_bagdirectory already exists, you must first delete it before running the executable.Now run the executable:ros2 run bag_recorder_nodes_py data_generator_executableNote that the executable runs and finishes very quickly.Now play back the created bag.ros2 bag play big_synthetic_bagOpen a second terminal and echo the/synthetictopic.ros2 topic echo /syntheticYou will see the data that was generated and stored in the bag printed to the console at a rate of one message per second. +Even though the bag was generated rapidly it is still played back at the rate the time stamps indicate.SummaryYou created a node that records data it receives on a topic into a bag. +You tested recording a bag using the node, and verified the data was recorded by playing back the bag. +This approach can be used to record a bag with additional data than it received over a topic, for example with results obtained from processing the received data. +You then went on to create a node and an executable to generate synthetic data and store it in a bag. +The latter approaches are useful especially for generating synthetic data that can be used, for example, as training sets. + +Code Examples: + +Language: unknown +sudo apt install ros-jazzy-rosbag2 + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 bag_recorder_nodes_py --dependencies rclpy rosbag2_py example_interfaces std_msgs + +Language: unknown +PythonbagwritingtutorialYourNameApache-2.0 + +Language: unknown +maintainer='Your Name',maintainer_email='you@email.com',description='Python bag writing tutorial',license='Apache-2.0', + +Language: unknown +importrclpyfromrclpy.nodeimportNodefromrclpy.serializationimportserialize_messagefromstd_msgs.msgimportStringimportrosbag2_pyclassSimpleBagRecorder(Node):def__init__(self):super().__init__('simple_bag_recorder')self.writer=rosbag2_py.SequentialWriter()storage_options=rosbag2_py._storage.StorageOptions(uri='my_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')self.writer.open(storage_options,converter_options)topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='chatter',type='std_msgs/msg/String',serialization_format='cdr')self.writer.create_topic(topic_info)self.subscription=self.create_subscription(String,'chatter',self.topic_callback,10)self.subscriptiondeftopic_callback(self,msg):self.writer.write('chatter',serialize_message(msg),self.get_clock().now().nanoseconds)defmain(args=None):rclpy.init(args=args)sbr=SimpleBagRecorder()rclpy.spin(sbr)rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +self.writer=rosbag2_py.SequentialWriter() + +Language: unknown +storage_options=rosbag2_py._storage.StorageOptions(uri='my_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')self.writer.open(storage_options,converter_options) + +Language: unknown +topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='chatter',type='std_msgs/msg/String',serialization_format='cdr')self.writer.create_topic(topic_info) + +Language: unknown +self.subscription=self.create_subscription(String,'chatter',self.topic_callback,10)self.subscription + +Language: unknown +deftopic_callback(self,msg):self.writer.write('chatter',serialize_message(msg),self.get_clock().now().nanoseconds) + +Language: unknown +defmain(args=None):rclpy.init(args=args)sbr=SimpleBagRecorder()rclpy.spin(sbr)rclpy.shutdown() + +Language: unknown +entry_points={'console_scripts':['simple_bag_recorder = bag_recorder_nodes_py.simple_bag_recorder:main',],}, + +Language: unknown +colcon build --packages-select bag_recorder_nodes_py + +Language: unknown +colcon build --packages-select bag_recorder_nodes_py + +Language: unknown +colcon build --merge-install --packages-select bag_recorder_nodes_py + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_recorder_nodes_py simple_bag_recorder + +Language: unknown +ros2 run demo_nodes_cpp talker + +Language: unknown +ros2 run demo_nodes_cpp listener + +Language: unknown +ros2 bag play my_bag + +Language: unknown +importrclpyfromrclpy.nodeimportNodefromrclpy.serializationimportserialize_messagefromexample_interfaces.msgimportInt32importrosbag2_pyclassDataGeneratorNode(Node):def__init__(self):super().__init__('data_generator_node')self.data=Int32()self.data.data=0self.writer=rosbag2_py.SequentialWriter()storage_options=rosbag2_py._storage.StorageOptions(uri='timed_synthetic_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')self.writer.open(storage_options,converter_options)topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='synthetic',type='example_interfaces/msg/Int32',serialization_format='cdr')self.writer.create_topic(topic_info)self.timer=self.create_timer(1,self.timer_callback)deftimer_callback(self):self.writer.write('synthetic',serialize_message(self.data),self.get_clock().now().nanoseconds)self.data.data+=1defmain(args=None):rclpy.init(args=args)dgn=DataGeneratorNode()rclpy.spin(dgn)rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +storage_options=rosbag2_py._storage.StorageOptions(uri='timed_synthetic_bag',storage_id='mcap') + +Language: unknown +topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='synthetic',type='example_interfaces/msg/Int32',serialization_format='cdr')self.writer.create_topic(topic_info) + +Language: unknown +self.timer=self.create_timer(1,self.timer_callback) + +Language: unknown +self.writer.write('synthetic',serialize_message(self.data),self.get_clock().now().nanoseconds) + +Language: unknown +entry_points={'console_scripts':['simple_bag_recorder = bag_recorder_nodes_py.simple_bag_recorder:main','data_generator_node = bag_recorder_nodes_py.data_generator_node:main',],}, + +Language: unknown +colcon build --packages-select bag_recorder_nodes_py + +Language: unknown +colcon build --packages-select bag_recorder_nodes_py + +Language: unknown +colcon build --merge-install --packages-select bag_recorder_nodes_py + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_recorder_nodes_py data_generator_node + +Language: unknown +ros2 bag play timed_synthetic_bag + +Language: unknown +ros2 topic echo /synthetic + +Language: unknown +fromrclpy.clockimportClockfromrclpy.durationimportDurationfromrclpy.serializationimportserialize_messagefromexample_interfaces.msgimportInt32importrosbag2_pydefmain(args=None):writer=rosbag2_py.SequentialWriter()storage_options=rosbag2_py._storage.StorageOptions(uri='big_synthetic_bag',storage_id='mcap')converter_options=rosbag2_py._storage.ConverterOptions('','')writer.open(storage_options,converter_options)topic_info=rosbag2_py._storage.TopicMetadata(id=0,name='synthetic',type='example_interfaces/msg/Int32',serialization_format='cdr')writer.create_topic(topic_info)time_stamp=Clock().now()foriiinrange(0,100):data=Int32()data.data=iiwriter.write('synthetic',serialize_message(data),time_stamp.nanoseconds)time_stamp+=Duration(seconds=1)if__name__=='__main__':main() + +Language: unknown +time_stamp=Clock().now()foriiinrange(0,100):data=Int32()data.data=iiwriter.write('synthetic',serialize_message(data),time_stamp.nanoseconds)time_stamp+=Duration(seconds=1) + +Language: unknown +entry_points={'console_scripts':['simple_bag_recorder = bag_recorder_nodes_py.simple_bag_recorder:main','data_generator_node = bag_recorder_nodes_py.data_generator_node:main','data_generator_executable = bag_recorder_nodes_py.data_generator_executable:main',],}, + +Language: unknown +colcon build --packages-select bag_recorder_nodes_py + +Language: unknown +colcon build --packages-select bag_recorder_nodes_py + +Language: unknown +colcon build --merge-install --packages-select bag_recorder_nodes_py + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run bag_recorder_nodes_py data_generator_executable + +Language: unknown +ros2 bag play big_synthetic_bag + +Language: unknown +ros2 topic echo /synthetic diff --git "a/exported_docs/ros2/Recording_and_playing_back_data\357\203\201.txt" "b/exported_docs/ros2/Recording_and_playing_back_data\357\203\201.txt" new file mode 100644 index 0000000..ae8a43b --- /dev/null +++ "b/exported_docs/ros2/Recording_and_playing_back_data\357\203\201.txt" @@ -0,0 +1,143 @@ +Title: Recording and playing back data +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Recording-And-Playing-Back-Data/Recording-And-Playing-Back-Data.html +Section: Installation +-------------------------------------------------------------------------------- + +Recording and playing back dataGoal:Record data published on a topic and a service so you can replay and examine it any time.Tutorial level:BeginnerTime:15 minutesContentsBackgroundPrerequisitesManaging Topic Data1 Setup2 Choose a topic3 Record topics4 Inspect topic data5 Play topic dataManaging Service Data1 Setup2 Check service availability3 Record services4 Inspect service data5 Play service dataSummaryNext stepsRelated contentBackgroundros2bagis a command line tool for recording data published on topics and services in your ROS 2 system. +It accumulates the data passed on any number of topics and services, then saves it in a database. +You can then replay the data to reproduce the results of your tests and experiments. +Recording topics and services is also a great way to share your work and allow others to recreate it.PrerequisitesYou should haveros2baginstalled as a part of your regular ROS 2 setup.If you need to install ROS 2, see theInstallation instructions.This tutorial talks about concepts covered in previous tutorials, likenodes,topicsandservices. +It also uses theturtlesim packageandService Introspection Demo.As always, don’t forget to source ROS 2 inevery new terminal you open.Managing Topic Data1 SetupYou’ll be recording your keyboard input in theturtlesimsystem to save and replay later on, so begin by starting up the/turtlesimand/teleop_turtlenodes.Open a new terminal and run:ros2 run turtlesim turtlesim_nodeOpen another terminal and run:ros2 run turtlesim turtle_teleop_keyLet’s also make a new directory to store our saved recordings, just as good practice:LinuxmacOSWindowsmkdir bag_filescd bag_filesmkdir bag_filescd bag_filesmd bag_filescd bag_files2 Choose a topicros2bagcan record data from messages published to topics. +To see the list of your system’s topics, open a new terminal and run the command:ros2 topic listWhich will return:/parameter_events/rosout/turtle1/cmd_vel/turtle1/color_sensor/turtle1/poseIn the topics tutorial, you learned that the/turtle_teleopnode publishes commands on the/turtle1/cmd_veltopic to make the turtle move in turtlesim.To see the data that/turtle1/cmd_velis publishing, run the command:ros2 topic echo /turtle1/cmd_velNothing will show up at first because no data is being published by the teleop. +Return to the terminal where you ran the teleop and select it so it’s active. +Use the arrow keys to move the turtle around, and you will see data being published on the terminal runningros2topicecho.linear:x: 2.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.0---3 Record topics3.1 Record a single topicTo record the data published to a topic use the command syntax:ros2 bag record Before running this command on your chosen topic, open a new terminal and move into thebag_filesdirectory you created earlier, because the rosbag file will save in the directory where you run it.Run the command:ros2 bag record /turtle1/cmd_velYou will see the following messages in the terminal (the date and time will be different):[INFO] [rosbag2_storage]: Opened database 'rosbag2_2019_10_11-05_18_45'.[INFO] [rosbag2_transport]: Listening for topics...[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...Nowros2bagis recording the data published on the/turtle1/cmd_veltopic. +Return to the teleop terminal and move the turtle around again. +The movements don’t matter, but try to make a recognizable pattern to see when you replay the data later.PressCtrl+Cto stop recording.The data will be accumulated in a new bag directory with a name in the pattern ofrosbag2_year_month_day-hour_minute_second. +This directory will contain ametadata.yamlalong with the bag file in the recorded format.3.2 Record multiple topicsYou can also record multiple topics, as well as change the name of the fileros2bagsaves to.Run the following command:ros2 bag record -o subset /turtle1/cmd_vel /turtle1/poseThe-ooption allows you to choose a unique name for your bag file. +The following string, in this casesubset, is the file name.To record more than one topic at a time, simply list each topic separated by a space.You will see the following message, confirming that both topics are being recorded.[INFO] [rosbag2_storage]: Opened database 'subset'.[INFO] [rosbag2_transport]: Listening for topics...[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/pose'[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...You can move the turtle around and pressCtrl+Cwhen you’re finished.NoteThere is another option you can add to the command,-a, which records all the topics on your system.4 Inspect topic dataYou can see details about your recording by running:ros2 bag info Running this command on thesubsetbag file will return a list of information on the file:ros2 bag info subsetFiles: subset.mcapBag size: 228.5 KiBStorage id: mcapDuration: 48.47sStart: Oct 11 2019 06:09:09.12 (1570799349.12)End Oct 11 2019 06:09:57.60 (1570799397.60)Messages: 3013Topic information: Topic: /turtle1/cmd_vel | Type: geometry_msgs/msg/Twist | Count: 9 | Serialization Format: cdrTopic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 3004 | Serialization Format: cdr5 Play topic dataBefore replaying the bag file, enterCtrl+Cin the terminal where the teleop is running. +Then make sure your turtlesim window is visible so you can see the bag file in action.Enter the command:ros2 bag play subsetThe terminal will return the message:[INFO] [rosbag2_storage]: Opened database 'subset'.Your turtle will follow the same path you entered while recording (though not 100% exactly; turtlesim is sensitive to small changes in the system’s timing).Because thesubsetfile recorded the/turtle1/posetopic, theros2bagplaycommand won’t quit for as long as you had turtlesim running, even if you weren’t moving.This is because as long as the/turtlesimnode is active, it publishes data on the/turtle1/posetopic at regular intervals. +You may have noticed in theros2baginfoexample result above that the/turtle1/cmd_veltopic’sCountinformation was only 9; that’s how many times we pressed the arrow keys while recording.Notice that/turtle1/posehas aCountvalue of over 3000; while we were recording, data was published on that topic 3000 times.To get an idea of how often position data is published, you can run the command:ros2 topic hz /turtle1/poseManaging Service Data1 SetupYou’ll be recording service data betweenintrospection_clientandintrospection_service, then display and replay that same data later on. +To record service data between service client and server,ServiceIntrospectionmust be enabled on the node.Let’s startintrospection_clientandintrospection_servicenodes and enableServiceIntrospection. +You can see more details forService Introspection Demo.Open a new terminal and runintrospection_service, enablingServiceIntrospection:ros2 run demo_nodes_cpp introspection_service --ros-args -p service_configure_introspection:=contentsOpen another terminal and runintrospection_client, enablingServiceIntrospection:ros2 run demo_nodes_cpp introspection_client --ros-args -p client_configure_introspection:=contents2 Check service availabilityros2bagcan only record data from available services. +To see the list of your system’s services, open a new terminal and run the command:ros2 service listWhich will return:/add_two_ints/introspection_client/describe_parameters/introspection_client/get_parameter_types/introspection_client/get_parameters/introspection_client/get_type_description/introspection_client/list_parameters/introspection_client/set_parameters/introspection_client/set_parameters_atomically/introspection_service/describe_parameters/introspection_service/get_parameter_types/introspection_service/get_parameters/introspection_service/get_type_description/introspection_service/list_parameters/introspection_service/set_parameters/introspection_service/set_parameters_atomicallyTo check ifServiceIntrospectionis enabled on the client and service, run the command:ros2 service echo --flow-style /add_two_intsYou should see service communication like below:info:event_type: REQUEST_SENTstamp:sec: 1713995389nanosec: 386809259client_gid: [1, 15, 96, 219, 162, 1, 108, 201, 0, 0, 0, 0, 0, 0, 21, 3]sequence_number: 133request: [{a: 2, b: 3}]response: []---3 Record servicesTo record service data, the following options are supported. +Service data can be recorded with topics at the same time.To record specific services:ros2 bag record --service To record all services:ros2 bag record --all-servicesRun the command:ros2 bag record --service /add_two_intsYou will see the following messages in the terminal (the date and time will be different):[INFO] [1713995957.643573503] [rosbag2_recorder]: Press SPACE for pausing/resuming[INFO] [1713995957.662067587] [rosbag2_recorder]: Event publisher thread: Starting[INFO] [1713995957.662067614] [rosbag2_recorder]: Listening for topics...[INFO] [1713995957.666048323] [rosbag2_recorder]: Subscribed to topic '/add_two_ints/_service_event'[INFO] [1713995957.666092458] [rosbag2_recorder]: Recording...Nowros2bagis recording the service data published on the/add_two_intsservice. +To stop the recording, enterCtrl+Cin the terminal.The data will be accumulated in a new bag directory with a name in the pattern ofrosbag2_year_month_day-hour_minute_second. +This directory will contain ametadata.yamlalong with the bag file in the recorded format.4 Inspect service dataYou can see details about your recording by running:ros2 bag info Running this command will return a list of information on the file:Files: rosbag2_2024_04_24-14_59_17_0.mcapBag size: 15.1 KiBStorage id: mcapROS Distro: rollingDuration: 9.211sStart: Apr 24 2024 14:59:17.676 (1713995957.676)End: Apr 24 2024 14:59:26.888 (1713995966.888)Messages: 0Topic information:Service: 1Service information: Service: /add_two_ints | Type: example_interfaces/srv/AddTwoInts | Event Count: 78 | Serialization Format: cdr5 Play service dataBefore replaying the bag file, enterCtrl+Cin the terminal whereintrospection_clientis running. +Whenintrospection_clientstops running,introspection_servicealso stops printing the result because there are no incoming requests.Replaying the service data from the bag file will start sending the requests tointrospection_service.Enter the command:ros2 bag play --publish-service-requests The terminal will return the message:[INFO] [1713997477.870856190] [rosbag2_player]: Set rate to 1[INFO] [1713997477.877417477] [rosbag2_player]: Adding keyboard callbacks.[INFO] [1713997477.877442404] [rosbag2_player]: Press SPACE for Pause/Resume[INFO] [1713997477.877447855] [rosbag2_player]: Press CURSOR_RIGHT for Play Next Message[INFO] [1713997477.877452655] [rosbag2_player]: Press CURSOR_UP for Increase Rate 10%[INFO] [1713997477.877456954] [rosbag2_player]: Press CURSOR_DOWN for Decrease Rate 10%[INFO] [1713997477.877573647] [rosbag2_player]: Playback until timestamp: -1Yourintrospection_serviceterminal will once again start printing the following service messages:[INFO] [1713997478.090466075] [introspection_service]: Incoming requesta: 2 b: 3This is becauseros2bagplaysends the service request data from the bag file to the/add_two_intsservice.We can also introspect service communication asros2bagplayis playing it back to verify theintrospection_service.Run this command beforeros2bagplayto see theintrospection_service:ros2 service echo --flow-style /add_two_intsYou can see the service request from the bag file and the service response fromintrospection_service.info:event_type: REQUEST_RECEIVEDstamp:sec: 1713998176nanosec: 372700698client_gid: [1, 15, 96, 219, 80, 2, 158, 123, 0, 0, 0, 0, 0, 0, 20, 4]sequence_number: 1request: [{a: 2, b: 3}]response: []---info:event_type: RESPONSE_SENTstamp:sec: 1713998176nanosec: 373016882client_gid: [1, 15, 96, 219, 80, 2, 158, 123, 0, 0, 0, 0, 0, 0, 20, 4]sequence_number: 1request: []response: [{sum: 5}]SummaryYou can record data passed on topics and services in your ROS 2 system using theros2bagcommand. +Whether you’re sharing your work with others or introspecting your own experiments, it’s a great tool to know about.Next stepsYou’ve completed the “Beginner: CLI Tools” tutorials! +The next step is tackling the “Beginner: Client Libraries” tutorials, starting withCreating a workspace.Related contentA more thorough explanation ofros2bagcan be found in the READMEhere. +For more information on service recording and playback can be found in the design documenthere. +For more information on QoS compatibility andros2bag, seerosbag2: Overriding QoS Policies. + +Code Examples: + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +mkdir bag_filescd bag_files + +Language: unknown +mkdir bag_filescd bag_files + +Language: unknown +md bag_filescd bag_files + +Language: unknown +ros2 topic list + +Language: unknown +/parameter_events/rosout/turtle1/cmd_vel/turtle1/color_sensor/turtle1/pose + +Language: unknown +ros2 topic echo /turtle1/cmd_vel + +Language: unknown +linear:x: 2.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.0--- + +Language: unknown +ros2 bag record + +Language: unknown +ros2 bag record /turtle1/cmd_vel + +Language: unknown +[INFO] [rosbag2_storage]: Opened database 'rosbag2_2019_10_11-05_18_45'.[INFO] [rosbag2_transport]: Listening for topics...[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery... + +Language: unknown +ros2 bag record -o subset /turtle1/cmd_vel /turtle1/pose + +Language: unknown +[INFO] [rosbag2_storage]: Opened database 'subset'.[INFO] [rosbag2_transport]: Listening for topics...[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/pose'[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery... + +Language: unknown +ros2 bag info + +Language: unknown +ros2 bag info subset + +Language: unknown +Files: subset.mcapBag size: 228.5 KiBStorage id: mcapDuration: 48.47sStart: Oct 11 2019 06:09:09.12 (1570799349.12)End Oct 11 2019 06:09:57.60 (1570799397.60)Messages: 3013Topic information: Topic: /turtle1/cmd_vel | Type: geometry_msgs/msg/Twist | Count: 9 | Serialization Format: cdrTopic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 3004 | Serialization Format: cdr + +Language: unknown +ros2 bag play subset + +Language: unknown +[INFO] [rosbag2_storage]: Opened database 'subset'. + +Language: unknown +ros2 topic hz /turtle1/pose + +Language: unknown +ros2 run demo_nodes_cpp introspection_service --ros-args -p service_configure_introspection:=contents + +Language: unknown +ros2 run demo_nodes_cpp introspection_client --ros-args -p client_configure_introspection:=contents + +Language: unknown +ros2 service list + +Language: unknown +/add_two_ints/introspection_client/describe_parameters/introspection_client/get_parameter_types/introspection_client/get_parameters/introspection_client/get_type_description/introspection_client/list_parameters/introspection_client/set_parameters/introspection_client/set_parameters_atomically/introspection_service/describe_parameters/introspection_service/get_parameter_types/introspection_service/get_parameters/introspection_service/get_type_description/introspection_service/list_parameters/introspection_service/set_parameters/introspection_service/set_parameters_atomically + +Language: unknown +ros2 service echo --flow-style /add_two_ints + +Language: unknown +info:event_type: REQUEST_SENTstamp:sec: 1713995389nanosec: 386809259client_gid: [1, 15, 96, 219, 162, 1, 108, 201, 0, 0, 0, 0, 0, 0, 21, 3]sequence_number: 133request: [{a: 2, b: 3}]response: []--- + +Language: unknown +ros2 bag record --service + +Language: unknown +ros2 bag record --all-services + +Language: unknown +ros2 bag record --service /add_two_ints + +Language: unknown +[INFO] [1713995957.643573503] [rosbag2_recorder]: Press SPACE for pausing/resuming[INFO] [1713995957.662067587] [rosbag2_recorder]: Event publisher thread: Starting[INFO] [1713995957.662067614] [rosbag2_recorder]: Listening for topics...[INFO] [1713995957.666048323] [rosbag2_recorder]: Subscribed to topic '/add_two_ints/_service_event'[INFO] [1713995957.666092458] [rosbag2_recorder]: Recording... + +Language: unknown +ros2 bag info + +Language: unknown +Files: rosbag2_2024_04_24-14_59_17_0.mcapBag size: 15.1 KiBStorage id: mcapROS Distro: rollingDuration: 9.211sStart: Apr 24 2024 14:59:17.676 (1713995957.676)End: Apr 24 2024 14:59:26.888 (1713995966.888)Messages: 0Topic information:Service: 1Service information: Service: /add_two_ints | Type: example_interfaces/srv/AddTwoInts | Event Count: 78 | Serialization Format: cdr + +Language: unknown +ros2 bag play --publish-service-requests + +Language: unknown +[INFO] [1713997477.870856190] [rosbag2_player]: Set rate to 1[INFO] [1713997477.877417477] [rosbag2_player]: Adding keyboard callbacks.[INFO] [1713997477.877442404] [rosbag2_player]: Press SPACE for Pause/Resume[INFO] [1713997477.877447855] [rosbag2_player]: Press CURSOR_RIGHT for Play Next Message[INFO] [1713997477.877452655] [rosbag2_player]: Press CURSOR_UP for Increase Rate 10%[INFO] [1713997477.877456954] [rosbag2_player]: Press CURSOR_DOWN for Decrease Rate 10%[INFO] [1713997477.877573647] [rosbag2_player]: Playback until timestamp: -1 + +Language: unknown +[INFO] [1713997478.090466075] [introspection_service]: Incoming requesta: 2 b: 3 + +Language: unknown +ros2 service echo --flow-style /add_two_ints + +Language: unknown +info:event_type: REQUEST_RECEIVEDstamp:sec: 1713998176nanosec: 372700698client_gid: [1, 15, 96, 219, 80, 2, 158, 123, 0, 0, 0, 0, 0, 0, 20, 4]sequence_number: 1request: [{a: 2, b: 3}]response: []---info:event_type: RESPONSE_SENTstamp:sec: 1713998176nanosec: 373016882client_gid: [1, 15, 96, 219, 80, 2, 158, 123, 0, 0, 0, 0, 0, 0, 20, 4]sequence_number: 1request: []response: [{sum: 5}] diff --git "a/exported_docs/ros2/Related_Projects\357\203\201.txt" "b/exported_docs/ros2/Related_Projects\357\203\201.txt" new file mode 100644 index 0000000..97f5bf4 --- /dev/null +++ "b/exported_docs/ros2/Related_Projects\357\203\201.txt" @@ -0,0 +1,10 @@ +Title: Related Projects +URL: https://docs.ros.org/en/jazzy/Related-Projects.html +Section: Installation +-------------------------------------------------------------------------------- + +Related ProjectsGazeboGazebo(gazebosim.org)and its predecessor Gazebo Classic are the first open source choice for 3D physics simulation of ROS-based robots.Large Community ProjectsLarge community projects involve multiple developers from all over the globe and are typically backed by a dedicated working group (cf.Project Governance).ros2_control(control.ros.org): Flexible framework for real-time control of robots implemented with ROS 2.Navigation2(nav2.org): Comprehensive and flexible navigation stack for mobile robots using ROS 2.MoveIt(moveit.ai): A rich platform for building manipulation applications featuring advanced kinematics, motion planning, control, collision checking, and much more.micro-ROS(micro.ros.org): A platform for putting ROS 2 onto microcontrollers, starting at less than 100 kB of RAM.Further Community ProjectsThe global ROS community develops and maintains hundreds of further packages on top of the core ROS 2 stack. +Some of them come with their own websites for documentation. +Your best entry point to discover these works is theROS Index(index.ros.org).Hint for developers:If you maintain aREADME.mdfile in the root of your package folder (which is not necessarily the root of your repository), this file is rendered into the overview page of your package atindex.ros.org. +The file may be used for documenting your package and supersedes the package documentation pages in the ROS Wiki from ROS 1. +See thefmi_adapter packageas an example.Company-driven ProjectsIntel ROS 2 ProjectsNVIDIA ROS 2 Projects \ No newline at end of file diff --git "a/exported_docs/ros2/Release_Track\357\203\201.txt" "b/exported_docs/ros2/Release_Track\357\203\201.txt" new file mode 100644 index 0000000..8b095e9 --- /dev/null +++ "b/exported_docs/ros2/Release_Track\357\203\201.txt" @@ -0,0 +1,55 @@ +Title: Release Track +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Releasing/Release-Track.html +Section: Installation +-------------------------------------------------------------------------------- + +Release TrackTable of ContentsWhat is a Track?Track ConfigurationsRelease Repository urlRepository NameUpstream Repository URIUpstream VCS TypeVersionRelease TagUpstream Devel BranchROS DistroPatches DirectoryRelease Repository Push URLWhat is a Track?Bloom requires the user to enter configuration information when releasing packages for the first time. +It is beneficial to store such configurations in the release repository so we don’t have to manually enter configurations that won’t change for subsequent releases.Since some of the configurations will differ when releasing the package for different ROS distributions, bloom usesrelease tracks to store the configurations for releasingper distribution. +By convention you should create tracks with the same name as the ROS distro you are releasing for.All release track configurations are stored intracks.yamlon the master branch of your release repository.Track ConfigurationsTrack configurations are explained in more detail along with the prompts from bloom.Release Repository urlThis is the url of your release repository, and should be of formhttps://github.com/ros2-gbp/my_repo-release.gitif your release repository is hosted on ros2-gbp.Noreasonabledefaultreleaserepositoryurlcouldbedeterminedfrompreviousreleases. +Releaserepositoryurl[pressentertoabort]:Paste your release repository URL and press Enter.Bloom may additionally ask you about initializing the new repository, as following:Freshlyinitializedgitrepositorydetected. +Aninitialemptycommitisgoingtobemade. +Continue[Y/n]?Simply press Enter to accept the default of yes.Repository NameThe repository name is trivial, but it is recommended to set this to the name of your project.RepositoryName:upstreamDefaultvalue,leavethisasupstreamifyouareunsureNameoftherepository(usedinthearchivename)['upstream']:Type the name of your project (eg.my_project) and press Enter.Upstream Repository URITheupstream repositoryis the repository where your source code is. +This is most likely an https link to your project hosted on a git hosting service such as GitHub or GitLab.UpstreamRepositoryURI:AnyvalidURI.Thisvariablecanbetemplated,forexampleansvnurlcanbetemplatedassuch:"https://svn.foo.com/foo/tags/foo-:{version}"wherethe:{version}tokenwillbereplacedwiththeversionforthisrelease.[None]:Make sure youuse the https address(eg.https://github.com/my_organization/my_repo.git) and not the ssh address.Upstream VCS TypeThis is theUpstream Repository URI’s version control system (VCS) type. +You must specify the type of vcs your repository is using, fromsvn,git,hgortar.UpstreamVCSType:svnUpstreamURIisasvnrepositorygitUpstreamURIisagitrepositoryhgUpstreamURIisahgrepositorytarUpstreamURIisatarball['git']:Most repositories will be using git, but some legacy repositories might be using hg or svn.VersionThis is the version of the package you are releasing. (eg.1.0.3)Version::{ask}Thismeansthattheuserwillbepromptedfortheversioneachrelease.Thisalsomeansthattheupstreamdevelwillbeignored.:{auto}Thismeanstheversionwillbeguessedfromthedevelbranch.Thismeansthatthedevelbranchmustbeset,thedevelbranchmustexist,andtheremustbeavalidpackage.xmlintheupstreamdevelbranch.Thiswillbetheversionused.Itmustbeupdatedforeachnewupstreamversion.[':{auto}']:Setting this to:{auto}(the default, and recommended setup) will automatically determine the version from the devel branch’s package.xml.Setting this to:{ask}will bring up a prompt asking for the version every time you run a release with bloom.Release TagThe Release Tag refers to which tag or branch you want to import the code from.ReleaseTag::{version}Thismeansthatthereleasetagwillmatchthe:{version}tag.Thiscanbefurthertemplated,forexample:"foo-:{version}"or"v:{version}"Thiscandescribeanyvcsreference.Forgitthatmeans{tag,branch,hash},forhgthatmeans{tag,branch,hash},forsvnthatmeansarevisionnumber.Fortarthisvaluedoublesasthesubdirectory(iftherepositoryisinfoo/ofthetarball,puttingfooherewillcausethecontentsoffoo/tobeimportedtoupstreaminsteadoffooitself).:{ask}Thismeanstheuserwillbepromptedforthereleasetagoneachrelease.:{none}Forsvnandtaronlyyoucansetthereleasetagto:{none},sothatitisignored.Forsvnthismeansnorevisionnumberisused.[':{version}']:Setting this to:{version}(the default, and recommended setup) will make the release tag match the version tag.A less common setup is to set this to a branch name to always pull in that branch at the time of release from the upstream project.Alternatively, if you want to be prompted to enter a different tag every time you do a release, enter:{ask}.:{ask}is useful if the upstream project has frequent tagged releases and you want to refer to the new tag every time you’re releasing.Upstream Devel BranchThe upstream devel branch is the name of the branch in yourupstream repository. +If you use separate branches for each ROS distribution, this field would be different for each release track. +It is used to determine the version of the package you are releasing whenVersionis set to:{auto}.UpstreamDevelBranch:Branchinupstreamrepositoryonwhichtosearchfortheversion.Thisisusedonlywhenversionissetto':{auto}'.[None]:To release from a branch calledjazzy, enterjazzy. +Leaving this asNonewould result in the version being determined from the default branch of your repository (this is not recommended).ROS DistroThis is the distribution you’re planning on releasing the package into.ROSDistro:ThiscanbeanyvalidROSdistro,e.g.indigo,kinetic,lunar,melodic['indigo']:If you plan on releasing into ROS jazzy, enterjazzy.Patches DirectoryThis is the directory where any additional patches to the releases are.PatchesDirectory:Thiscanbeanyvalidrelativepathinthebloombranch.Thecontentsofthisfolderwillbeoverlaidontotheupstreambranchaftereachimport-upstream.Additionally,anypackage.xmlfilesfoundintheoverlaywillhavethe:{version}stringreplacedwiththecurrentversionbeingreleased.:{none}Usethisifyouwanttodisableoverlayingoffiles.[None]:Adding additional patches to a release is a rarely used feature. +For almost all packages, this should be left as the defaultNone.Release Repository Push URLReleaseRepositoryPushURL::{none}Thisindicatesthatthedefaultreleaseurlshouldbeused.(optional)Usedwhenpushingtoremotereleaserepositories.Thisisonlyneededwhenthereleaseuriwhichisintherosdistrofileisnotwritable.Thisisuseful,forexample,whenareleaserwouldliketouseasshurltopushratherthanahttps://url.[None]:Can be left as the default in most cases. + +Code Examples: + +Language: unknown +Noreasonabledefaultreleaserepositoryurlcouldbedeterminedfrompreviousreleases. +Releaserepositoryurl[pressentertoabort]: + +Language: unknown +Freshlyinitializedgitrepositorydetected. +Aninitialemptycommitisgoingtobemade. +Continue[Y/n]? + +Language: unknown +RepositoryName:upstreamDefaultvalue,leavethisasupstreamifyouareunsureNameoftherepository(usedinthearchivename)['upstream']: + +Language: unknown +UpstreamRepositoryURI:AnyvalidURI.Thisvariablecanbetemplated,forexampleansvnurlcanbetemplatedassuch:"https://svn.foo.com/foo/tags/foo-:{version}"wherethe:{version}tokenwillbereplacedwiththeversionforthisrelease.[None]: + +Language: unknown +UpstreamVCSType:svnUpstreamURIisasvnrepositorygitUpstreamURIisagitrepositoryhgUpstreamURIisahgrepositorytarUpstreamURIisatarball['git']: + +Language: unknown +Version::{ask}Thismeansthattheuserwillbepromptedfortheversioneachrelease.Thisalsomeansthattheupstreamdevelwillbeignored.:{auto}Thismeanstheversionwillbeguessedfromthedevelbranch.Thismeansthatthedevelbranchmustbeset,thedevelbranchmustexist,andtheremustbeavalidpackage.xmlintheupstreamdevelbranch.Thiswillbetheversionused.Itmustbeupdatedforeachnewupstreamversion.[':{auto}']: + +Language: unknown +ReleaseTag::{version}Thismeansthatthereleasetagwillmatchthe:{version}tag.Thiscanbefurthertemplated,forexample:"foo-:{version}"or"v:{version}"Thiscandescribeanyvcsreference.Forgitthatmeans{tag,branch,hash},forhgthatmeans{tag,branch,hash},forsvnthatmeansarevisionnumber.Fortarthisvaluedoublesasthesubdirectory(iftherepositoryisinfoo/ofthetarball,puttingfooherewillcausethecontentsoffoo/tobeimportedtoupstreaminsteadoffooitself).:{ask}Thismeanstheuserwillbepromptedforthereleasetagoneachrelease.:{none}Forsvnandtaronlyyoucansetthereleasetagto:{none},sothatitisignored.Forsvnthismeansnorevisionnumberisused.[':{version}']: + +Language: unknown +UpstreamDevelBranch:Branchinupstreamrepositoryonwhichtosearchfortheversion.Thisisusedonlywhenversionissetto':{auto}'.[None]: + +Language: unknown +ROSDistro:ThiscanbeanyvalidROSdistro,e.g.indigo,kinetic,lunar,melodic['indigo']: + +Language: unknown +PatchesDirectory:Thiscanbeanyvalidrelativepathinthebloombranch.Thecontentsofthisfolderwillbeoverlaidontotheupstreambranchaftereachimport-upstream.Additionally,anypackage.xmlfilesfoundintheoverlaywillhavethe:{version}stringreplacedwiththecurrentversionbeingreleased.:{none}Usethisifyouwanttodisableoverlayingoffiles.[None]: + +Language: unknown +ReleaseRepositoryPushURL::{none}Thisindicatesthatthedefaultreleaseurlshouldbeused.(optional)Usedwhenpushingtoremotereleaserepositories.Thisisonlyneededwhenthereleaseuriwhichisintherosdistrofileisnotwritable.Thisisuseful,forexample,whenareleaserwouldliketouseasshurltopushratherthanahttps://url.[None]: diff --git "a/exported_docs/ros2/Releasing_a_Package\357\203\201.txt" "b/exported_docs/ros2/Releasing_a_Package\357\203\201.txt" new file mode 100644 index 0000000..b61f982 --- /dev/null +++ "b/exported_docs/ros2/Releasing_a_Package\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Releasing a Package +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Releasing/Releasing-a-Package.html +Section: Installation +-------------------------------------------------------------------------------- + +Releasing a PackageReleasing a package makes your package available on the public ROS 2 buildfarm.This will:Make your package available to be installed via package managers (eg.apton Ubuntu) for all supported Linux platforms in a ROS distribution as described inREP 2000.Allow your package to have API documentation automatically generated.Make your package part of theROS Index.(Optionally) Allow you to have automatic CI run for pull requests in your repository.Follow one of the guides below to get your package released:Index Your Packages- if this is the first release for the packageFirst Time Release- if this is the first release for the package, but it is already indexedSubsequent Releases- if you are releasing a new version of a package that has already been releasedAfter successfully following the instructions, your package will be released into the ROS ecosystem on the next distro synchronization! \ No newline at end of file diff --git "a/exported_docs/ros2/Roadmap\357\203\201.txt" "b/exported_docs/ros2/Roadmap\357\203\201.txt" new file mode 100644 index 0000000..dde4dc7 --- /dev/null +++ "b/exported_docs/ros2/Roadmap\357\203\201.txt" @@ -0,0 +1,11 @@ +Title: Roadmap +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project/Roadmap.html +Section: Installation +-------------------------------------------------------------------------------- + +RoadmapTable of ContentsKilted RoadmapPlanned releasesContributing to ROS 2This page describes planned work for ROS 2. +The set of planned features and development efforts should provide insight into the overall direction of ROS 2. +If you would like to see other features on the roadmap, please get in touch with us atinfo@openrobotics.org.Kilted RoadmapKilted Kaiju is the ROS 2 release expected in May 2025. +See therelease pagefor a detailed timeline.The items in the roadmap below are the major features being worked on by the ROS 2 community. +The “Size” is an estimated size of the task, whereSmallmeans person-days to complete,Mediummeans person-weeks to complete, andLargemeans person-months to complete.If you are working on a feature for ROS 2 and would like to have it listed, please open a pull request toROS 2 Documentation. +If you’d like to take on one of these tasks, pleaseget in touch with us.TaskSizeOwnerExpected CompletionMakermw_zenoh_cppa Tier-1 RMWLargeIntrinsicMay 2025Planned releasesPlease see theDistributions pagefor the timeline of and information about future distributions.Contributing to ROS 2Looking for something to work on, or just want to help out? Here are a few resources to get you going.TheContributingguide describes how to make a contribution to ROS 2.Check out the list ofFeature Ideasfor inspiration.For more information on the design of ROS 2 please seedesign.ros2.org.The core code for ROS 2 is in theros2 GitHub organization.The Discourse forum/mailing list for discussing ROS 2 design isng-ros.Questions should be asked onRobotics Stack Exchange, make sure to include at least theros2tag and the rosdistro version you are running, e.g.jazzy. \ No newline at end of file diff --git "a/exported_docs/ros2/Rolling_Ridley_(rolling)\357\203\201.txt" "b/exported_docs/ros2/Rolling_Ridley_(rolling)\357\203\201.txt" new file mode 100644 index 0000000..63f0b30 --- /dev/null +++ "b/exported_docs/ros2/Rolling_Ridley_(rolling)\357\203\201.txt" @@ -0,0 +1,9 @@ +Title: Rolling Ridley (rolling) +URL: https://docs.ros.org/en/jazzy/Releases/Release-Rolling-Ridley.html +Section: Installation +-------------------------------------------------------------------------------- + +Rolling Ridley (rolling)Table of ContentsCurrently Supported PlatformsInstallationNew features and changes in this releaseRolling Ridleyis a rolling development release of ROS 2.WarningRolling Ridley is continuously updated and is subject to in-place updates which will at times include breaking changes. +It is used for ROS 2 development and by maintainers who want their packages released and ready for the next stable distribution. +We recommend that most users of ROS 2 use the lateststable distribution.For more information seeREP-2002Currently Supported PlatformsRolling Ridley is currently supported on the following platforms:Tier 1 platforms:Ubuntu 24.04 (Noble):amd64andarm64Windows 10 (Visual Studio 2019)Tier 3 platforms:Debian Buster (10):amd64,arm64andarm32Mac macOS 10.14 (Mojave)OpenEmbedded Thud (2.6) / webOS OSE:arm32andx86InstallationInstall Rolling RidleyNew features and changes in this releaseRolling Ridley is an ongoing development distribution. +Changes between the current stable release and the upcoming one can be found on the page for theupcoming release. \ No newline at end of file diff --git "a/exported_docs/ros2/Running_ROS_2_nodes_in_Docker_[community-contributed]\357\203\201.txt" "b/exported_docs/ros2/Running_ROS_2_nodes_in_Docker_[community-contributed]\357\203\201.txt" new file mode 100644 index 0000000..df7a36c --- /dev/null +++ "b/exported_docs/ros2/Running_ROS_2_nodes_in_Docker_[community-contributed]\357\203\201.txt" @@ -0,0 +1,37 @@ +Title: Running ROS 2 nodes in Docker [community-contributed] +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Run-2-nodes-in-single-or-separate-docker-containers.html +Section: Installation +-------------------------------------------------------------------------------- + +Running ROS 2 nodes in Docker [community-contributed]Run two nodes in a single docker containerPull the ROS docker image with tag “jazzy-desktop”.dockerpullosrf/ros:jazzy-desktopRun the image in a container in interactive mode.$dockerrun-itosrf/ros:jazzy-desktop +root@:/#Your best friend is theros2command line help now.root@:/#ros2--helpE.g. list all installed packages.root@:/#ros2pkglist(youwillseealistofpackages)E.g. list all executables:root@:/#ros2pkgexecutables(youwillseealistof)Run a minimal example of 2 C++ nodes (1 topic subscriberlistener, 1 topic publishertalker) from the packagedemo_nodes_cppin this container:ros2rundemo_nodes_cpplistener&ros2rundemo_nodes_cpptalkerRun two nodes in two separate docker containersOpen a terminal. Run the image in a container in interactive mode and launch a topic publisher (executabletalkerfrom the packagedemo_nodes_cpp) withros2run:dockerrun-it--rmosrf/ros:jazzy-desktopros2rundemo_nodes_cpptalkerOpen a second terminal. Run the image in a container in interactive mode and launch a topic subscriber (executablelistenerfrom the packagedemo_nodes_cpp) withros2run:dockerrun-it--rmosrf/ros:jazzy-desktopros2rundemo_nodes_cpplistenerAs an alternative to the command line invocation, you can create adocker-compose.ymlfile (here version 2) with the following (minimal) content:version:'2'services:talker:image:osrf/ros:jazzy-desktopcommand:ros2 run demo_nodes_cpp talkerlistener:image:osrf/ros:jazzy-desktopcommand:ros2 run demo_nodes_cpp listenerdepends_on:-talkerTo run the containers calldockercomposeupin the same directory. You can close the containers withCtrl+C. + +Code Examples: + +Language: unknown +dockerpullosrf/ros:jazzy-desktop + +Language: unknown +$dockerrun-itosrf/ros:jazzy-desktop +root@:/# + +Language: unknown +root@:/#ros2--help + +Language: unknown +root@:/#ros2pkglist(youwillseealistofpackages) + +Language: unknown +root@:/#ros2pkgexecutables(youwillseealistof) + +Language: unknown +ros2rundemo_nodes_cpplistener&ros2rundemo_nodes_cpptalker + +Language: unknown +dockerrun-it--rmosrf/ros:jazzy-desktopros2rundemo_nodes_cpptalker + +Language: unknown +dockerrun-it--rmosrf/ros:jazzy-desktopros2rundemo_nodes_cpplistener + +Language: unknown +version:'2'services:talker:image:osrf/ros:jazzy-desktopcommand:ros2 run demo_nodes_cpp talkerlistener:image:osrf/ros:jazzy-desktopcommand:ros2 run demo_nodes_cpp listenerdepends_on:-talker diff --git "a/exported_docs/ros2/Running_Tests_in_ROS_2_from_the_Command_Line\357\203\201.txt" "b/exported_docs/ros2/Running_Tests_in_ROS_2_from_the_Command_Line\357\203\201.txt" new file mode 100644 index 0000000..8ab769f --- /dev/null +++ "b/exported_docs/ros2/Running_Tests_in_ROS_2_from_the_Command_Line\357\203\201.txt" @@ -0,0 +1,17 @@ +Title: Running Tests in ROS 2 from the Command Line +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Testing/CLI.html +Section: Installation +-------------------------------------------------------------------------------- + +Running Tests in ROS 2 from the Command LineBuild and run your testsTo compile and run the tests, simply run thetestverb fromcolcon.colcon test --ctest-args tests [package_selection_args](wherepackage_selection_argsare optional package selection arguments forcolconto limit which packages are built and run)Sourcing the workspacebefore testing should not be necessary.colcontestmakes sure that the tests run with the right environment, have access to their dependencies, etc.Examine Test ResultsTo see the results, simply run thetest-resultverb fromcolcon.colcon test-result --allTo see the exact test cases which fail, use the--verboseflag:colcon test-result --all --verboseDebugging tests with GDBFor detailed guidance on debugging tests using GDB, refer to theGDB Tutorial. + +Code Examples: + +Language: unknown +colcon test --ctest-args tests [package_selection_args] + +Language: unknown +colcon test-result --all + +Language: unknown +colcon test-result --all --verbose diff --git "a/exported_docs/ros2/Services\357\203\201.txt" "b/exported_docs/ros2/Services\357\203\201.txt" new file mode 100644 index 0000000..ecf7b03 --- /dev/null +++ "b/exported_docs/ros2/Services\357\203\201.txt" @@ -0,0 +1,20 @@ +Title: Services +URL: https://docs.ros.org/en/jazzy/Concepts/Basic/About-Services.html +Section: Installation +-------------------------------------------------------------------------------- + +ServicesTable of ContentsService serverService clientIn ROS 2, a service refers to a remote procedure call. +In other words, a node can make a remote procedure call to another node which will do a computation and return a result.This structure is reflected in how a service message definition looks:uint32request---uint32responseIn ROS 2, services are expected to return quickly, as the client is generally waiting on the result. +Services should never be used for longer running processes, in particular processes that might need to be preempted for exceptional situations. +If you have a service that will be doing a long-running computation, consider using anactioninstead.Services are identified by a service name, which looks much like a topic name (but is in a different namespace).A service consists of two parts: the service server and the service client.Service serverA service server is the entity that will accept a remote procedure request, and perform some computation on it. +For instance, suppose the ROS 2 message contains the following:uint32auint32b---uint32sumThe service server would be the entity that receives this message, addsaandbtogether, and returns thesum.NoteThere should only ever be one service server per service name. +It is undefined which service server will receive client requests in the case of multiple service servers on the same service name.Service clientA service client is an entity that will request a remote service server to perform a computation on its behalf. +Following from the example above, the service client is the entity that creates the initial message containingaandb, and waits for the service server to compute the sum and return the result.Unlike the service server, there can be arbitrary numbers of service clients using the same service name. + +Code Examples: + +Language: unknown +uint32request---uint32response + +Language: unknown +uint32auint32b---uint32sum diff --git "a/exported_docs/ros2/Setting_access_controls\357\203\201.txt" "b/exported_docs/ros2/Setting_access_controls\357\203\201.txt" new file mode 100644 index 0000000..2bf755c --- /dev/null +++ "b/exported_docs/ros2/Setting_access_controls\357\203\201.txt" @@ -0,0 +1,58 @@ +Title: Setting access controls +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Security/Access-Controls.html +Section: Installation +-------------------------------------------------------------------------------- + +Setting access controlsGoal:Limit the topics a node can use.Tutorial level:AdvancedTime:20 minutesContentsBackgroundModifypermissions.xmlSign the policy fileLaunch the nodeUse the templatesBackgroundBefore proceeding ensure you have completed theSetting up securitytutorial.Permissions are quite flexible and can be used to control many behaviors within the ROS graph.For this tutorial, we demonstrate a policy which only allows publishing messages on the defaultchattertopic. +This would prevent, for instance, remapping the topic when launching the listener or using the same security enclaves for another purpose.In order to enforce this policy, we need to update thepermissions.xmlfile and re-sign it before launching the node. +This can be done by modifying the permissions file by hand, or by using XML templates.Modifypermissions.xmlBegin by making a backup of your permissions files, and openpermissions.xmlfor editing:cd~/sros2_demo/demo_keystore/enclaves/talker_listener/talker +mvpermissions.p7spermissions.p7s~ +mvpermissions.xmlpermissions.xml~ +vipermissions.xmlWe will be modifying theforand. +The topics in this XML file use the DDS naming format, not the ROS name. +Find details on mapping topic names between ROS and DDS in theTopic and Service Names design document.Paste the following XML content intopermission.xml, save the file and exit the text editor. +This shows thechatterandrosoutROS topics renamed to the DDSrt/chatterandrt/rosouttopics, respectively:CN=/talker_listener/talker2021-06-01T16:57:532031-05-31T16:57:530rt/chatterrt/rosoutrt/parameter_events*/talker/*rt/parameter_events*/talker/*0ros_discovery_inforos_discovery_infoDENYThis policy allows the talker to publish on thechatterand therosouttopics. +It also allows includes publish and subscribe permissions needed for the talker node to manage parameters (a requirement for all nodes). +Discovery permissions remain unchanged from the original template.Sign the policy fileThis next command creates the new S/MIME signed policy filepermissions.p7sfrom the updated XML filepermissions.xml. +The file must be signed with the Permissions CA certificate,which requires access to the Permission CA private key. +If the private key has been protected, additional steps may be required to unlock and use it accoring to your security plan.opensslsmime-sign-text-inpermissions.xml-outpermissions.p7s\--signerpermissions_ca.cert.pem\-inkey~/sros2_demo/demo_keystore/private/permissions_ca.key.pemLaunch the nodeWith the updated permissions in place, we can launch the node successfully using the same command used in prior tutorials:ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talkerHowever, attempting to remap thechattertopic prevents the node from launching (note that this requires theROS_SECURITY_STRATEGYset toEnforce).ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker\--remapchatter:=not_chatterUse the templatesSecurity policies can quickly become confusing, so thesros2utilities add the ability to create policies from templates. +Do this by using thesample policy fileprovided in thesros2repository. +Let’s creates a policy for both thetalkerand thelistenerto only use thechattertopic.Begin by downloading thesros2repository with the sample policy files:gitclonehttps://github.com/ros2/sros2.git/tmp/sros2Then use thecreate_permissionverb while pointing to the sample policy to generate the XML permission files:ros2securitycreate_permissiondemo_keystore\/talker_listener/talker\/tmp/sros2/sros2/test/policies/sample.policy.xml +ros2securitycreate_permissiondemo_keystore\/talker_listener/listener\/tmp/sros2/sros2/test/policies/sample.policy.xmlThese permission files allow nodes to only publish or subscribe to thechattertopic, and enable communications required for parameters.In one terminal with security enabled as in previous security tutorials, run thetalkerdemo program:ros2rundemo_nodes_cpptalker--ros-args-e/talker_listener/talkerIn another terminal do the same with thelistenerprogram:ros2rundemo_nodes_pylistener--ros-args-e/talker_listener/listenerAt this point, yourtalkerandlistenernodes will be communicating securely using explicit access control lists. +However, the following attempt for thelistenernode to subscribe to a topic other thanchatterwill fail:ros2rundemo_nodes_pylistener--ros-args--enclave/talker_listener/listener\--remapchatter:=not_chatter + +Code Examples: + +Language: unknown +cd~/sros2_demo/demo_keystore/enclaves/talker_listener/talker +mvpermissions.p7spermissions.p7s~ +mvpermissions.xmlpermissions.xml~ +vipermissions.xml + +Language: unknown +CN=/talker_listener/talker2021-06-01T16:57:532031-05-31T16:57:530rt/chatterrt/rosoutrt/parameter_events*/talker/*rt/parameter_events*/talker/*0ros_discovery_inforos_discovery_infoDENY + +Language: unknown +opensslsmime-sign-text-inpermissions.xml-outpermissions.p7s\--signerpermissions_ca.cert.pem\-inkey~/sros2_demo/demo_keystore/private/permissions_ca.key.pem + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker\--remapchatter:=not_chatter + +Language: unknown +gitclonehttps://github.com/ros2/sros2.git/tmp/sros2 + +Language: unknown +ros2securitycreate_permissiondemo_keystore\/talker_listener/talker\/tmp/sros2/sros2/test/policies/sample.policy.xml +ros2securitycreate_permissiondemo_keystore\/talker_listener/listener\/tmp/sros2/sros2/test/policies/sample.policy.xml + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args-e/talker_listener/talker + +Language: unknown +ros2rundemo_nodes_pylistener--ros-args-e/talker_listener/listener + +Language: unknown +ros2rundemo_nodes_pylistener--ros-args--enclave/talker_listener/listener\--remapchatter:=not_chatter diff --git "a/exported_docs/ros2/Setting_up_a_Reset_Handler\357\203\201.txt" "b/exported_docs/ros2/Setting_up_a_Reset_Handler\357\203\201.txt" new file mode 100644 index 0000000..9bf5a18 --- /dev/null +++ "b/exported_docs/ros2/Setting_up_a_Reset_Handler\357\203\201.txt" @@ -0,0 +1,36 @@ +Title: Setting up a Reset Handler +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Simulation-Reset-Handler.html +Section: Installation +-------------------------------------------------------------------------------- + +Setting up a Reset HandlerGoal:Extend a robot simulation with a reset handler to restart nodes when the reset button of Webots is pressed.Tutorial level:AdvancedTime:10 minutesContentsBackgroundPrerequisitesReset Handler for Simple Cases (Controllers Only)Reset Handler for Multiple Nodes (No Shutdown Required)Reset Handler Requiring Node ShutdownSummaryBackgroundIn this tutorial, you will learn how to implement a reset handler in a robot simulation using Webots. +The Webots reset button reverts the world to the initial state and restarts controllers. +It is convenient as it quickly resets the simulation, but in the context of ROS 2, robot controllers are not started again making the simulation stop. +The reset handler allows you to restart specific nodes or perform additional actions when the reset button in Webots is pressed. +This can be useful for scenarios where you need to reset the state of your simulation or restart specific components without completely restarting the complete ROS system.PrerequisitesBefore proceeding with this tutorial, make sure you have completed the following:Understanding of ROS 2 nodes and topics covered in the beginnerTutorials.Knowledge of Webots and ROS 2 and its interface package.Familiarity withSetting up a robot simulation (Basic).Reset Handler for Simple Cases (Controllers Only)In the launch file of your package, add therespawnparameter.defgenerate_launch_description():robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path}],# Every time one resets the simulation the controller is automatically respawnedrespawn=True)# Starts Webotswebots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]))returnLaunchDescription([webots,robot_driver])On reset, Webots kills all driver nodes. +Therefore, to start them again after reset, you should set therespawnproperty of the driver node toTrue. +It will ensure driver nodes are up and running after the reset.Reset Handler for Multiple Nodes (No Shutdown Required)If you have some other nodes that have to be started along with the driver node (e.g.ros2_controlnodes), then you can use theOnProcessExitevent handler:defget_ros2_control_spawners(*args):# Declare here all nodes that must be restarted at simulation resetros_control_node=Node(package='controller_manager',executable='spawner',arguments=['diffdrive_controller'])return[ros_control_node]defgenerate_launch_description():robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path}],# Every time one resets the simulation the controller is automatically respawnedrespawn=True)# Starts Webotswebots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]))# Declare the reset handler that respawns nodes when robot_driver exitsreset_handler=launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=robot_driver,on_exit=get_ros2_control_spawners,))returnLaunchDescription([webots,robot_driver,reset_handler]+get_ros2_control_spawners())It is not possible to use therespawnproperty on theros2_controlnode, as the spawner exits during launch time and not when the simulation is reset. +Instead we should declare a list of nodes in a function (e.g.get_ros2_control_spawners). +The nodes of this list are started along other nodes when executing the launch file. +With thereset_handler, the function is also declared as action to start when therobot_drivernode exits, which corresponds to the moment when the simulation is reset in the Webots interface. +Therobot_drivernode still has therespawnproperty set toTrue, so that it gets restarted along withros2_controlnodes.Reset Handler Requiring Node ShutdownWith the current ROS 2 launch API, there is no way to make the reset work in launch files where nodes need to be shutdown before the restart (e.g.Nav2orRViz). +The reason is that currently, ROS 2 doesn’t allow to shutdown specific nodes from a launch file. +There is a solution, but it requires to manually restart nodes after pushing the reset button.Webots needs to be started in a specific launch file without other nodes.defgenerate_launch_description():# Starts Webotswebots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]))returnLaunchDescription([webots])A second launch file must be started from another process. +This launch file contains all other nodes, including robot controllers/plugins, Navigation2 nodes, RViz, state publishers, etc.defgenerate_launch_description():robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path}])ros_control_node=Node(package='controller_manager',executable='spawner',arguments=['diffdrive_controller'])nav2_node=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('nav2_bringup'),'launch','bringup_launch.py')),launch_arguments=[('map',nav2_map),('params_file',nav2_params),],)rviz=Node(package='rviz2',executable='rviz2',output='screen')# Declare the handler that shuts all nodes down when robot_driver exitsshutdown_handler=launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=robot_driver,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))returnLaunchDescription([robot_driver,ros_control_node,nav2_node,rviz,shutdown_handler])The second launch file contains a handler that triggers a shutdown event when the driver node exits (which is the case when the simulation is reset). +This second launch file must be manually restarted from the command line after pressing the reset button.SummaryIn this tutorial, you learned how to implement a reset handler in a robot simulation using Webots. +The reset handler allows you to restart specific nodes or perform additional actions when the reset button in Webots is pressed. +You explored different approaches based on the complexity of your simulation and the requirements of your nodes. + +Code Examples: + +Language: unknown +defgenerate_launch_description():robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path}],# Every time one resets the simulation the controller is automatically respawnedrespawn=True)# Starts Webotswebots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]))returnLaunchDescription([webots,robot_driver]) + +Language: unknown +defget_ros2_control_spawners(*args):# Declare here all nodes that must be restarted at simulation resetros_control_node=Node(package='controller_manager',executable='spawner',arguments=['diffdrive_controller'])return[ros_control_node]defgenerate_launch_description():robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path}],# Every time one resets the simulation the controller is automatically respawnedrespawn=True)# Starts Webotswebots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]))# Declare the reset handler that respawns nodes when robot_driver exitsreset_handler=launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=robot_driver,on_exit=get_ros2_control_spawners,))returnLaunchDescription([webots,robot_driver,reset_handler]+get_ros2_control_spawners()) + +Language: unknown +defgenerate_launch_description():# Starts Webotswebots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]))returnLaunchDescription([webots]) + +Language: unknown +defgenerate_launch_description():robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path}])ros_control_node=Node(package='controller_manager',executable='spawner',arguments=['diffdrive_controller'])nav2_node=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('nav2_bringup'),'launch','bringup_launch.py')),launch_arguments=[('map',nav2_map),('params_file',nav2_params),],)rviz=Node(package='rviz2',executable='rviz2',output='screen')# Declare the handler that shuts all nodes down when robot_driver exitsshutdown_handler=launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=robot_driver,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))returnLaunchDescription([robot_driver,ros_control_node,nav2_node,rviz,shutdown_handler]) diff --git "a/exported_docs/ros2/Setting_up_a_robot_simulation_(Advanced)\357\203\201.txt" "b/exported_docs/ros2/Setting_up_a_robot_simulation_(Advanced)\357\203\201.txt" new file mode 100644 index 0000000..81b0f8f --- /dev/null +++ "b/exported_docs/ros2/Setting_up_a_robot_simulation_(Advanced)\357\203\201.txt" @@ -0,0 +1,79 @@ +Title: Setting up a robot simulation (Advanced) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Advanced.html +Section: Installation +-------------------------------------------------------------------------------- + +Setting up a robot simulation (Advanced)Goal:Extend a robot simulation with an obstacle avoider node.Tutorial level:AdvancedTime:20 minutesContentsBackgroundPrerequisitesTasks1 Updatingmy_robot.urdf2 Creating a ROS node to avoid obstacles3 Updating additional files4 Test the obstacle avoidance codeSummaryNext stepsBackgroundIn this tutorial you will extend the package created in the first part of the tutorial:Setting up a robot simulation (Basic). +The aim is to implement a ROS 2 node that avoids obstacles using the robot’s distance sensors. +This tutorial focuses on using robot devices with thewebots_ros2_driverinterface.PrerequisitesThis is a continuation of the first part of the tutorial:Setting up a robot simulation (Basic). +It is mandatory to start with the first part to set up the custom packages and necessary files.This tutorial is compatible with version 2023.1.0 ofwebots_ros2and Webots R2023b, as well as upcoming versions.Tasks1 Updatingmy_robot.urdfAs mentioned inSetting up a robot simulation (Basic),webots_ros2_drivercontains plugins to interface most of Webots devices with ROS 2 directly. +These plugins can be loaded using thetag in the URDF file of the robot. +Thereferenceattribute should match the Webots devicenameparameter. +The list of all existing interfaces and the corresponding parameters can be foundon the devices reference page. +For available devices that are not configured in the URDF file, the interface will be automatically created and default values will be used for ROS parameters (e.g.updaterate,topicname, andframename).Inmy_robot.urdfreplace the whole contents with:PythonC++/left_sensortrue/right_sensortrue/left_sensortrue/right_sensortrueIn addition to your custom plugin, thewebots_ros2_driverwill parse thetags referring to theDistanceSensornodes and use the standard parameters in thetags to enable the sensors and name their topics.2 Creating a ROS node to avoid obstaclesPythonC++The robot will use a standard ROS node to detect the wall and send motor commands to avoid it. +In themy_package/my_package/folder, create a file namedobstacle_avoider.pywith this code:importrclpyfromrclpy.nodeimportNodefromsensor_msgs.msgimportRangefromgeometry_msgs.msgimportTwistMAX_RANGE=0.15classObstacleAvoider(Node):def__init__(self):super().__init__('obstacle_avoider')self.__publisher=self.create_publisher(Twist,'cmd_vel',1)self.create_subscription(Range,'left_sensor',self.__left_sensor_callback,1)self.create_subscription(Range,'right_sensor',self.__right_sensor_callback,1)def__left_sensor_callback(self,message):self.__left_sensor_value=message.rangedef__right_sensor_callback(self,message):self.__right_sensor_value=message.rangecommand_message=Twist()command_message.linear.x=0.1ifself.__left_sensor_value<0.9*MAX_RANGEorself.__right_sensor_value<0.9*MAX_RANGE:command_message.angular.z=-2.0self.__publisher.publish(command_message)defmain(args=None):rclpy.init(args=args)avoider=ObstacleAvoider()rclpy.spin(avoider)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)avoider.destroy_node()rclpy.shutdown()if__name__=='__main__':main()This node will create a publisher for the command and subscribe to the sensors topics here:self.__publisher=self.create_publisher(Twist,'cmd_vel',1)self.create_subscription(Range,'left_sensor',self.__left_sensor_callback,1)self.create_subscription(Range,'right_sensor',self.__right_sensor_callback,1)When a measurement is received from the left sensor it will be copied to a member field:def__left_sensor_callback(self,message):self.__left_sensor_value=message.rangeFinally, a message will be sent to the/cmd_veltopic when a measurement from the right sensor is received. +Thecommand_messagewill register at least a forward speed inlinear.xin order to make the robot move when no obstacle is detected. +If any of the two sensors detect an obstacle,command_messagewill also register a rotational speed inangular.zin order to make the robot turn right.def__right_sensor_callback(self,message):self.__right_sensor_value=message.rangecommand_message=Twist()command_message.linear.x=0.1ifself.__left_sensor_value<0.9*MAX_RANGEorself.__right_sensor_value<0.9*MAX_RANGE:command_message.angular.z=-2.0self.__publisher.publish(command_message)The robot will use a standard ROS node to detect the wall and send motor commands to avoid it. +In themy_package/include/my_packagefolder, create a header file namedObstacleAvoider.hppwith this code:#include#include"geometry_msgs/msg/twist.hpp"#include"rclcpp/rclcpp.hpp"#include"sensor_msgs/msg/range.hpp"classObstacleAvoider:publicrclcpp::Node{public:explicitObstacleAvoider();private:voidleftSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg);voidrightSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg);rclcpp::Publisher::SharedPtrpublisher_;rclcpp::Subscription::SharedPtrleft_sensor_sub_;rclcpp::Subscription::SharedPtrright_sensor_sub_;doubleleft_sensor_value{0.0};doubleright_sensor_value{0.0};};In themy_package/srcfolder, create a source file namedObstacleAvoider.cppwith this code:#include"my_package/ObstacleAvoider.hpp"#define MAX_RANGE 0.15ObstacleAvoider::ObstacleAvoider():Node("obstacle_avoider"){publisher_=create_publisher("/cmd_vel",1);left_sensor_sub_=create_subscription("/left_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->leftSensorCallback(msg);});right_sensor_sub_=create_subscription("/right_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->rightSensorCallback(msg);});}voidObstacleAvoider::leftSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){left_sensor_value=msg->range;}voidObstacleAvoider::rightSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){right_sensor_value=msg->range;autocommand_message=std::make_unique();command_message->linear.x=0.1;if(left_sensor_value<0.9*MAX_RANGE||right_sensor_value<0.9*MAX_RANGE){command_message->angular.z=-2.0;}publisher_->publish(std::move(command_message));}intmain(intargc,char*argv[]){rclcpp::init(argc,argv);autoavoider=std::make_shared();rclcpp::spin(avoider);rclcpp::shutdown();return0;}This node will create a publisher for the command and subscribe to the sensors topics here:publisher_=create_publisher("/cmd_vel",1);left_sensor_sub_=create_subscription("/left_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->leftSensorCallback(msg);});right_sensor_sub_=create_subscription("/right_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->rightSensorCallback(msg);});When a measurement is received from the left sensor it will be copied to a member field:voidObstacleAvoider::leftSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){left_sensor_value=msg->range;}Finally, a message will be sent to the/cmd_veltopic when a measurement from the right sensor is received. +Thecommand_messagewill register at least a forward speed inlinear.xin order to make the robot move when no obstacle is detected. +If any of the two sensors detect an obstacle,command_messagewill also register a rotational speed inangular.zin order to make the robot turn right.voidObstacleAvoider::rightSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){right_sensor_value=msg->range;autocommand_message=std::make_unique();command_message->linear.x=0.1;if(left_sensor_value<0.9*MAX_RANGE||right_sensor_value<0.9*MAX_RANGE){command_message->angular.z=-2.0;}publisher_->publish(std::move(command_message));}3 Updating additional filesYou have to modify these two other files to launch your new node.PythonC++Editsetup.pyand replace'console_scripts'with:'console_scripts':['my_robot_driver = my_package.my_robot_driver:main','obstacle_avoider = my_package.obstacle_avoider:main'],This will add an entry point for theobstacle_avoidernode.EditCMakeLists.txtand add the compilation and installation of theobstacle_avoider:cmake_minimum_required(VERSION3.5)project(my_package)if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD14)endif()# Besides the package specific dependencies we also need the `pluginlib` and `webots_ros2_driver`find_package(ament_cmakeREQUIRED)find_package(rclcppREQUIRED)find_package(std_msgsREQUIRED)find_package(geometry_msgsREQUIRED)find_package(pluginlibREQUIRED)find_package(webots_ros2_driverREQUIRED)# Export the plugin configuration filepluginlib_export_plugin_description_file(webots_ros2_drivermy_robot_driver.xml)# Obstacle avoiderinclude_directories(include)add_executable(obstacle_avoidersrc/ObstacleAvoider.cpp)ament_target_dependencies(obstacle_avoiderrclcppgeometry_msgssensor_msgs)install(TARGETSobstacle_avoiderDESTINATIONlib/${PROJECT_NAME})install(DIRECTORYinclude/DESTINATIONinclude)# MyRobotDriver libraryadd_library(${PROJECT_NAME}SHAREDsrc/MyRobotDriver.cpp)target_include_directories(${PROJECT_NAME}PRIVATEinclude)ament_target_dependencies(${PROJECT_NAME}pluginlibrclcppwebots_ros2_driver)install(TARGETS${PROJECT_NAME}ARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)# Install additional directories.install(DIRECTORYlaunchresourceworldsDESTINATIONshare/${PROJECT_NAME}/)ament_export_include_directories(include)ament_export_libraries(${PROJECT_NAME})ament_package()Go to the filerobot_launch.pyand replace it with:importosimportlaunchfromlaunch_ros.actionsimportNodefromlaunchimportLaunchDescriptionfromament_index_python.packagesimportget_package_share_directoryfromwebots_ros2_driver.webots_launcherimportWebotsLauncherfromwebots_ros2_driver.webots_controllerimportWebotsControllerdefgenerate_launch_description():package_dir=get_package_share_directory('my_package')robot_description_path=os.path.join(package_dir,'resource','my_robot.urdf')webots=WebotsLauncher(world=os.path.join(package_dir,'worlds','my_world.wbt'))my_robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path},])obstacle_avoider=Node(package='my_package',executable='obstacle_avoider',)returnLaunchDescription([webots,my_robot_driver,obstacle_avoider,launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))])This will create anobstacle_avoidernode that will be included in theLaunchDescription.4 Test the obstacle avoidance codeLaunch the simulation from a terminal in your ROS 2 workspace:LinuxWindowsmacOSFrom a terminal in your ROS 2 workspace run:colcon buildsource install/local_setup.bashros2 launch my_package robot_launch.pyFrom a terminal in your WSL ROS 2 workspace run:colcon buildexport WEBOTS_HOME=/mnt/c/Program\ Files/Webotssource install/local_setup.bashros2 launch my_package robot_launch.pyBe sure to use the/mntprefix in front of your path to the Webots installation folder to access the Windows file system from WSL.In a terminal of the host machine (not in the VM), if not done already, specify the Webots installation folder (e.g./Applications/Webots.app) and start the server using the following commands:export WEBOTS_HOME=/Applications/Webots.apppython3 local_simulation_server.pyNote that the server keeps running once the ROS 2 nodes are ended. +You don’t need to restart it every time you want to launch a new simulation. +From a terminal in the Linux VM in your ROS 2 workspace, build and launch your custom package with:cd ~/ros2_wscolcon buildsource install/local_setup.bashros2 launch my_package robot_launch.pyYour robot should go forward and before hitting the wall it should turn clockwise. +You can pressCtrl+F10in Webots or go to theViewmenu,OptionalRenderingandShowDistanceSensorRaysto display the range of the distance sensors of the robot.SummaryIn this tutorial, you extended the basic simulation with a obstacle avoider ROS 2 node that publishes velocity commands based on the distance sensor values of the robot.Next stepsYou might want to improve the plugin or create new nodes to change the behavior of the robot. +You can also implement a reset handler to automatically restart your ROS nodes when the simulation is reset from the Webots interface:Setting up a Reset Handler. + +Code Examples: + +Language: unknown +/left_sensortrue/right_sensortrue + +Language: unknown +/left_sensortrue/right_sensortrue + +Language: unknown +importrclpyfromrclpy.nodeimportNodefromsensor_msgs.msgimportRangefromgeometry_msgs.msgimportTwistMAX_RANGE=0.15classObstacleAvoider(Node):def__init__(self):super().__init__('obstacle_avoider')self.__publisher=self.create_publisher(Twist,'cmd_vel',1)self.create_subscription(Range,'left_sensor',self.__left_sensor_callback,1)self.create_subscription(Range,'right_sensor',self.__right_sensor_callback,1)def__left_sensor_callback(self,message):self.__left_sensor_value=message.rangedef__right_sensor_callback(self,message):self.__right_sensor_value=message.rangecommand_message=Twist()command_message.linear.x=0.1ifself.__left_sensor_value<0.9*MAX_RANGEorself.__right_sensor_value<0.9*MAX_RANGE:command_message.angular.z=-2.0self.__publisher.publish(command_message)defmain(args=None):rclpy.init(args=args)avoider=ObstacleAvoider()rclpy.spin(avoider)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)avoider.destroy_node()rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +self.__publisher=self.create_publisher(Twist,'cmd_vel',1)self.create_subscription(Range,'left_sensor',self.__left_sensor_callback,1)self.create_subscription(Range,'right_sensor',self.__right_sensor_callback,1) + +Language: unknown +def__left_sensor_callback(self,message):self.__left_sensor_value=message.range + +Language: unknown +def__right_sensor_callback(self,message):self.__right_sensor_value=message.rangecommand_message=Twist()command_message.linear.x=0.1ifself.__left_sensor_value<0.9*MAX_RANGEorself.__right_sensor_value<0.9*MAX_RANGE:command_message.angular.z=-2.0self.__publisher.publish(command_message) + +Language: unknown +#include#include"geometry_msgs/msg/twist.hpp"#include"rclcpp/rclcpp.hpp"#include"sensor_msgs/msg/range.hpp"classObstacleAvoider:publicrclcpp::Node{public:explicitObstacleAvoider();private:voidleftSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg);voidrightSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg);rclcpp::Publisher::SharedPtrpublisher_;rclcpp::Subscription::SharedPtrleft_sensor_sub_;rclcpp::Subscription::SharedPtrright_sensor_sub_;doubleleft_sensor_value{0.0};doubleright_sensor_value{0.0};}; + +Language: unknown +#include"my_package/ObstacleAvoider.hpp"#define MAX_RANGE 0.15ObstacleAvoider::ObstacleAvoider():Node("obstacle_avoider"){publisher_=create_publisher("/cmd_vel",1);left_sensor_sub_=create_subscription("/left_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->leftSensorCallback(msg);});right_sensor_sub_=create_subscription("/right_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->rightSensorCallback(msg);});}voidObstacleAvoider::leftSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){left_sensor_value=msg->range;}voidObstacleAvoider::rightSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){right_sensor_value=msg->range;autocommand_message=std::make_unique();command_message->linear.x=0.1;if(left_sensor_value<0.9*MAX_RANGE||right_sensor_value<0.9*MAX_RANGE){command_message->angular.z=-2.0;}publisher_->publish(std::move(command_message));}intmain(intargc,char*argv[]){rclcpp::init(argc,argv);autoavoider=std::make_shared();rclcpp::spin(avoider);rclcpp::shutdown();return0;} + +Language: unknown +publisher_=create_publisher("/cmd_vel",1);left_sensor_sub_=create_subscription("/left_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->leftSensorCallback(msg);});right_sensor_sub_=create_subscription("/right_sensor",1,[this](constsensor_msgs::msg::Range::SharedPtrmsg){returnthis->rightSensorCallback(msg);}); + +Language: unknown +voidObstacleAvoider::leftSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){left_sensor_value=msg->range;} + +Language: unknown +voidObstacleAvoider::rightSensorCallback(constsensor_msgs::msg::Range::SharedPtrmsg){right_sensor_value=msg->range;autocommand_message=std::make_unique();command_message->linear.x=0.1;if(left_sensor_value<0.9*MAX_RANGE||right_sensor_value<0.9*MAX_RANGE){command_message->angular.z=-2.0;}publisher_->publish(std::move(command_message));} + +Language: unknown +'console_scripts':['my_robot_driver = my_package.my_robot_driver:main','obstacle_avoider = my_package.obstacle_avoider:main'], + +Language: unknown +cmake_minimum_required(VERSION3.5)project(my_package)if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD14)endif()# Besides the package specific dependencies we also need the `pluginlib` and `webots_ros2_driver`find_package(ament_cmakeREQUIRED)find_package(rclcppREQUIRED)find_package(std_msgsREQUIRED)find_package(geometry_msgsREQUIRED)find_package(pluginlibREQUIRED)find_package(webots_ros2_driverREQUIRED)# Export the plugin configuration filepluginlib_export_plugin_description_file(webots_ros2_drivermy_robot_driver.xml)# Obstacle avoiderinclude_directories(include)add_executable(obstacle_avoidersrc/ObstacleAvoider.cpp)ament_target_dependencies(obstacle_avoiderrclcppgeometry_msgssensor_msgs)install(TARGETSobstacle_avoiderDESTINATIONlib/${PROJECT_NAME})install(DIRECTORYinclude/DESTINATIONinclude)# MyRobotDriver libraryadd_library(${PROJECT_NAME}SHAREDsrc/MyRobotDriver.cpp)target_include_directories(${PROJECT_NAME}PRIVATEinclude)ament_target_dependencies(${PROJECT_NAME}pluginlibrclcppwebots_ros2_driver)install(TARGETS${PROJECT_NAME}ARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)# Install additional directories.install(DIRECTORYlaunchresourceworldsDESTINATIONshare/${PROJECT_NAME}/)ament_export_include_directories(include)ament_export_libraries(${PROJECT_NAME})ament_package() + +Language: unknown +importosimportlaunchfromlaunch_ros.actionsimportNodefromlaunchimportLaunchDescriptionfromament_index_python.packagesimportget_package_share_directoryfromwebots_ros2_driver.webots_launcherimportWebotsLauncherfromwebots_ros2_driver.webots_controllerimportWebotsControllerdefgenerate_launch_description():package_dir=get_package_share_directory('my_package')robot_description_path=os.path.join(package_dir,'resource','my_robot.urdf')webots=WebotsLauncher(world=os.path.join(package_dir,'worlds','my_world.wbt'))my_robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path},])obstacle_avoider=Node(package='my_package',executable='obstacle_avoider',)returnLaunchDescription([webots,my_robot_driver,obstacle_avoider,launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))]) + +Language: unknown +colcon buildsource install/local_setup.bashros2 launch my_package robot_launch.py + +Language: unknown +colcon buildexport WEBOTS_HOME=/mnt/c/Program\ Files/Webotssource install/local_setup.bashros2 launch my_package robot_launch.py + +Language: unknown +export WEBOTS_HOME=/Applications/Webots.apppython3 local_simulation_server.py + +Language: unknown +cd ~/ros2_wscolcon buildsource install/local_setup.bashros2 launch my_package robot_launch.py diff --git "a/exported_docs/ros2/Setting_up_a_robot_simulation_(Basic)\357\203\201.txt" "b/exported_docs/ros2/Setting_up_a_robot_simulation_(Basic)\357\203\201.txt" new file mode 100644 index 0000000..e0214cc --- /dev/null +++ "b/exported_docs/ros2/Setting_up_a_robot_simulation_(Basic)\357\203\201.txt" @@ -0,0 +1,160 @@ +Title: Setting up a robot simulation (Basic) +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Basic.html +Section: Installation +-------------------------------------------------------------------------------- + +Setting up a robot simulation (Basic)Goal:Setup a robot simulation and control it from ROS 2.Tutorial level:AdvancedTime:30 minutesContentsBackgroundPrerequisitesTasks1 Create the package structure2 Setup the simulation world3 Edit themy_robot_driverplugin4 Create themy_robot.urdffile5 Create the launch file6 Edit additional files7 Test the codeSummaryNext stepsBackgroundIn this tutorial, you are going to use the Webots robot simulator to set-up and run a very simple ROS 2 simulation scenario.Thewebots_ros2package provides an interface between ROS 2 and Webots. +It includes several sub-packages, but in this tutorial, you are going to use only thewebots_ros2_driversub-package to implement a Python or C++ plugin controlling a simulated robot. +Some other sub-packages contain demos with different robots such as the TurtleBot3. +They are documented in theWebots ROS 2 examplespage.PrerequisitesIt is recommended to understand basic ROS principles covered in the beginnerTutorials. +In particular,Using turtlesim, ros2, and rqt,Understanding topics,Creating a workspace,Creating a packageandCreating a launch fileare useful prerequisites.LinuxWindowsmacOSThe Linux and ROS commands of this tutorial can be run in a standard Linux terminal. +The following pageInstallation (Ubuntu)explains how to install thewebots_ros2package on Linux.The Linux and ROS commands of this tutorial must be run in a WSL (Windows Subsystem for Linux) environment. +The following pageInstallation (Windows)explains how to install thewebots_ros2package on Windows.The Linux and ROS commands of this tutorial must be run in a pre-configured Linux Virtual Machine (VM). +The following pageInstallation (macOS)explains how to install thewebots_ros2package on macOS.This tutorial is compatible with version 2023.1.0 ofwebots_ros2and Webots R2023b, as well as upcoming versions.Tasks1 Create the package structureLet’s organize the code in a custom ROS 2 package. +Create a new package namedmy_packagefrom thesrcfolder of your ROS 2 workspace. +Change the current directory of your terminal toros2_ws/srcand run:PythonC++ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_robot_driver my_package --dependencies rclpy geometry_msgs webots_ros2_driverThe--node-namemy_robot_driveroption will create amy_robot_driver.pytemplate Python plugin in themy_packagesubfolder that you will modify later. +The--dependenciesrclpygeometry_msgswebots_ros2_driveroption specifies the packages needed by themy_robot_driver.pyplugin in thepackage.xmlfile.Let’s add alaunchand aworldsfolder inside themy_packagefolder.cd my_packagemkdir launchmkdir worldsYou should end up with the following folder structure:src/└── my_package/├── launch/├── my_package/│ ├── __init__.py│ └── my_robot_driver.py├── resource/│ └── my_package├── test/│ ├── test_copyright.py│ ├── test_flake8.py│ └── test_pep257.py├── worlds/├── package.xml├── setup.cfg└── setup.pyros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name MyRobotDriver my_package --dependencies rclcpp geometry_msgs webots_ros2_driver pluginlibThe--node-nameMyRobotDriveroption will create aMyRobotDriver.cpptemplate C++ plugin in themy_package/srcsubfolder that you will modify later. +The--dependenciesrclcppgeometry_msgswebots_ros2_driverpluginliboption specifies the packages needed by theMyRobotDriverplugin in thepackage.xmlfile.Let’s add alaunch, aworldsand aresourcefolder inside themy_packagefolder.cd my_packagemkdir launchmkdir worldsmkdir resourceTwo additional files must be created: the header file forMyRobotDriverand themy_robot_driver.xmlpluginlib description file.touch my_robot_driver.xmltouch include/my_package/MyRobotDriver.hppYou should end up with the following folder structure:src/└── my_package/├── include/│ └── my_package/│ └── MyRobotDriver.hpp├── launch/├── resource/├── src/│ └── MyRobotDriver.cpp├── worlds/├── CMakeList.txt├── my_robot_driver.xml└── package.xml2 Setup the simulation worldYou will need a world file containing a robot to launch your simulation.Downloadthisworldfileand move it insidemy_package/worlds/.This is actually a fairly simple text file you can visualize in a text editor. +A simple robot is already included in thismy_world.wbtworld file.NoteIn case you want to learn how to create your own robot model in Webots, you can check thistutorial.3 Edit themy_robot_driverpluginThewebots_ros2_driversub-package automatically creates a ROS 2 interface for most sensors. +More details on existing device interfaces and how to configure them is given in the second part of the tutorial:Setting up a robot simulation (Advanced). +In this task, you will extend this interface by creating your own custom plugin. +This custom plugin is a ROS node equivalent to a robot controller. +You can use it to access theWebots robot APIand create your own topics and services to control your robot.NoteThe purpose of this tutorial is to show a basic example with a minimum number of dependencies. +However, you could avoid the use of this plugin by using anotherwebots_ros2sub-package namedwebots_ros2_control, introducing a new dependency. +This other sub-package creates an interface with theros2_controlpackage that facilitates the control of a differential wheeled robot.PythonC++Openmy_package/my_package/my_robot_driver.pyin your favorite editor and replace its contents with the following:importrclpyfromgeometry_msgs.msgimportTwistHALF_DISTANCE_BETWEEN_WHEELS=0.045WHEEL_RADIUS=0.025classMyRobotDriver:definit(self,webots_node,properties):self.__robot=webots_node.robotself.__left_motor=self.__robot.getDevice('left wheel motor')self.__right_motor=self.__robot.getDevice('right wheel motor')self.__left_motor.setPosition(float('inf'))self.__left_motor.setVelocity(0)self.__right_motor.setPosition(float('inf'))self.__right_motor.setVelocity(0)self.__target_twist=Twist()rclpy.init(args=None)self.__node=rclpy.create_node('my_robot_driver')self.__node.create_subscription(Twist,'cmd_vel',self.__cmd_vel_callback,1)def__cmd_vel_callback(self,twist):self.__target_twist=twistdefstep(self):rclpy.spin_once(self.__node,timeout_sec=0)forward_speed=self.__target_twist.linear.xangular_speed=self.__target_twist.angular.zcommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUScommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUSself.__left_motor.setVelocity(command_motor_left)self.__right_motor.setVelocity(command_motor_right)As you can see, theMyRobotDriverclass implements three methods.The first method, namedinit(self,...), is actually the ROS node counterpart of the Python__init__(self,...)constructor. +Theinitmethod always takes two arguments:Thewebots_nodeargument contains a reference on the Webots instance.Thepropertiesargument is a dictionary created from the XML tags given in the URDF files (4 Create the my_robot.urdf file) and allows you to pass parameters to the controller.The robot instance from the simulationself.__robotcan be used to access theWebots robot API. +Then, it gets the two motor instances and initializes them with a target position and a target velocity. +Finally a ROS node is created and a callback method is registered for a ROS topic named/cmd_velthat will handleTwistmessages.definit(self,webots_node,properties):self.__robot=webots_node.robotself.__left_motor=self.__robot.getDevice('left wheel motor')self.__right_motor=self.__robot.getDevice('right wheel motor')self.__left_motor.setPosition(float('inf'))self.__left_motor.setVelocity(0)self.__right_motor.setPosition(float('inf'))self.__right_motor.setVelocity(0)self.__target_twist=Twist()rclpy.init(args=None)self.__node=rclpy.create_node('my_robot_driver')self.__node.create_subscription(Twist,'cmd_vel',self.__cmd_vel_callback,1)Then comes the implementation of the__cmd_vel_callback(self,twist)callback private method that will be called for eachTwistmessage received on the/cmd_veltopic and will save it in theself.__target_twistmember variable.def__cmd_vel_callback(self,twist):self.__target_twist=twistFinally, thestep(self)method is called at every time step of the simulation. +The call torclpy.spin_once()is needed to keep the ROS node running smoothly. +At each time step, the method will retrieve the desiredforward_speedandangular_speedfromself.__target_twist. +As the motors are controlled with angular velocities, the method will then convert theforward_speedandangular_speedinto individual commands for each wheel. +This conversion depends on the structure of the robot, more specifically on the radius of the wheel and the distance between them.defstep(self):rclpy.spin_once(self.__node,timeout_sec=0)forward_speed=self.__target_twist.linear.xangular_speed=self.__target_twist.angular.zcommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUScommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUSself.__left_motor.setVelocity(command_motor_left)self.__right_motor.setVelocity(command_motor_right)Openmy_package/include/my_package/MyRobotDriver.hppin your favorite editor and replace its contents with the following:#ifndef WEBOTS_ROS2_PLUGIN_EXAMPLE_HPP#define WEBOTS_ROS2_PLUGIN_EXAMPLE_HPP#include"rclcpp/macros.hpp"#include"webots_ros2_driver/PluginInterface.hpp"#include"webots_ros2_driver/WebotsNode.hpp"#include"geometry_msgs/msg/twist.hpp"#include"rclcpp/rclcpp.hpp"namespacemy_robot_driver{classMyRobotDriver:publicwebots_ros2_driver::PluginInterface{public:voidstep()override;voidinit(webots_ros2_driver::WebotsNode*node,std::unordered_map¶meters)override;private:rclcpp::Subscription::SharedPtrcmd_vel_subscription_;geometry_msgs::msg::Twistcmd_vel_msg;WbDeviceTagright_motor;WbDeviceTagleft_motor;};}// namespace my_robot_driver#endifThe classMyRobotDriveris defined, which inherits from thewebots_ros2_driver::PluginInterfaceclass. +The plugin has to overridestep(...)andinit(...)functions. +More details are given in theMyRobotDriver.cppfile. +Several helper methods, callbacks and member variables that will be used internally by the plugin are declared privately.Then, openmy_package/src/MyRobotDriver.cppin your favorite editor and replace its contents with the following:#include"my_package/MyRobotDriver.hpp"#include"rclcpp/rclcpp.hpp"#include#include#include#include#define HALF_DISTANCE_BETWEEN_WHEELS 0.045#define WHEEL_RADIUS 0.025namespacemy_robot_driver{voidMyRobotDriver::init(webots_ros2_driver::WebotsNode*node,std::unordered_map¶meters){right_motor=wb_robot_get_device("right wheel motor");left_motor=wb_robot_get_device("left wheel motor");wb_motor_set_position(left_motor,INFINITY);wb_motor_set_velocity(left_motor,0.0);wb_motor_set_position(right_motor,INFINITY);wb_motor_set_velocity(right_motor,0.0);cmd_vel_subscription_=node->create_subscription("/cmd_vel",rclcpp::SensorDataQoS().reliable(),[this](constgeometry_msgs::msg::Twist::SharedPtrmsg){this->cmd_vel_msg.linear=msg->linear;this->cmd_vel_msg.angular=msg->angular;});}voidMyRobotDriver::step(){autoforward_speed=cmd_vel_msg.linear.x;autoangular_speed=cmd_vel_msg.angular.z;autocommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;autocommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;wb_motor_set_velocity(left_motor,command_motor_left);wb_motor_set_velocity(right_motor,command_motor_right);}}// namespace my_robot_driver#include"pluginlib/class_list_macros.hpp"PLUGINLIB_EXPORT_CLASS(my_robot_driver::MyRobotDriver,webots_ros2_driver::PluginInterface)TheMyRobotDriver::initmethod is executed once the plugin is loaded by thewebots_ros2_driverpackage. +It takes two arguments:A pointer to theWebotsNodedefined bywebots_ros2_driver, which allows to access the ROS 2 node functions.Theparametersargument is an unordered map of strings, created from the XML tags given in the URDF files (4 Create the my_robot.urdf file) and allows to pass parameters to the controller. It is not used in this example.It initializes the plugin by setting up the robot motors, setting their positions and velocities, and subscribing to the/cmd_veltopic.voidMyRobotDriver::init(webots_ros2_driver::WebotsNode*node,std::unordered_map¶meters){right_motor=wb_robot_get_device("right wheel motor");left_motor=wb_robot_get_device("left wheel motor");wb_motor_set_position(left_motor,INFINITY);wb_motor_set_velocity(left_motor,0.0);wb_motor_set_position(right_motor,INFINITY);wb_motor_set_velocity(right_motor,0.0);cmd_vel_subscription_=node->create_subscription("/cmd_vel",rclcpp::SensorDataQoS().reliable(),[this](constgeometry_msgs::msg::Twist::SharedPtrmsg){this->cmd_vel_msg.linear=msg->linear;this->cmd_vel_msg.angular=msg->angular;});}The subscription callback is declared as a lambda function, that will be called for each Twist message received on the/cmd_veltopic and will save it in thecmd_vel_msgmember variable.[this](constgeometry_msgs::msg::Twist::SharedPtrmsg){this->cmd_vel_msg.linear=msg->linear;this->cmd_vel_msg.angular=msg->angular;}Thestep()method is called at every time step of the simulation. +At each time step, the method will retrieve the desiredforward_speedandangular_speedfromcmd_vel_msg. +As the motors are controlled with angular velocities, the method will then convert theforward_speedandangular_speedinto individual commands for each wheel. +This conversion depends on the structure of the robot, more specifically on the radius of the wheel and the distance between them.voidMyRobotDriver::step(){autoforward_speed=cmd_vel_msg.linear.x;autoangular_speed=cmd_vel_msg.angular.z;autocommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;autocommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;wb_motor_set_velocity(left_motor,command_motor_left);wb_motor_set_velocity(right_motor,command_motor_right);}The final lines of the file define the end of themy_robot_drivernamespace and include a macro to export theMyRobotDriverclass as a plugin using thePLUGINLIB_EXPORT_CLASSmacro. +This allows the plugin to be loaded by the Webots ROS2 driver at runtime.#include"pluginlib/class_list_macros.hpp"PLUGINLIB_EXPORT_CLASS(my_robot_driver::MyRobotDriver,webots_ros2_driver::PluginInterface)NoteWhile the plugin is implemented in C++, the C API must be used to interact with the Webots controller library.4 Create themy_robot.urdffileYou now have to create a URDF file to declare theMyRobotDriverplugin. +This will allow thewebots_ros2_driverROS node to launch the plugin and connect it to the target robot.In themy_package/resourcefolder create a text file namedmy_robot.urdfwith this content:PythonC++Thetypeattribute specifies the path to the class given by the hierarchical structure of files.webots_ros2_driveris responsible for loading the class based on the specified package and modules.Thetypeattribute specifies the namespace and class name to load.pluginlibis responsible for loading the class based on the specified information.NoteThis simple URDF file doesn’t contain any link or joint information about the robot as it is not needed in this tutorial. +However, URDF files usually contain much more information as explained in theURDFtutorial.NoteHere the plugin does not take any input parameter, but this can be achieved with a tag containing the parameter name.PythonC++someValuesomeValueThis is namely used to pass parameters to existing Webots device plugins (seeSetting up a robot simulation (Advanced)).5 Create the launch fileLet’s create the launch file to easily launch the simulation and the ROS controller with a single command. +In themy_package/launchfolder create a new text file namedrobot_launch.pywith this code:importosimportlaunchfromlaunchimportLaunchDescriptionfromament_index_python.packagesimportget_package_share_directoryfromwebots_ros2_driver.webots_launcherimportWebotsLauncherfromwebots_ros2_driver.webots_controllerimportWebotsControllerdefgenerate_launch_description():package_dir=get_package_share_directory('my_package')robot_description_path=os.path.join(package_dir,'resource','my_robot.urdf')webots=WebotsLauncher(world=os.path.join(package_dir,'worlds','my_world.wbt'))my_robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path},])returnLaunchDescription([webots,my_robot_driver,launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))])TheWebotsLauncherobject is a custom action that allows you to start a Webots simulation instance. +You have to specify in the constructor which world file the simulator will open.webots=WebotsLauncher(world=os.path.join(package_dir,'worlds','my_world.wbt'))Then, the ROS node interacting with the simulated robot is created. +This node, namedWebotsController, is located in thewebots_ros2_driverpackage.LinuxWindowsmacOSThe node will be able to communicate with the simulated robot by using a custom protocol based on IPC and shared memory.The node (in WSL) will be able to communicate with the simulated robot (in Webots on native Windows) through a TCP connection.The node (in the docker container) will be able to communicate with the simulated robot (in Webots on native macOS) through a TCP connection.In your case, you need to run a single instance of this node, because you have a single robot in the simulation. +But if you had more robots in the simulation, you would have to run one instance of this node per robot. +Therobot_nameparameter is used to define the name of the robot the driver should connect to. +Therobot_descriptionparameter holds the path to the URDF file which refers to theMyRobotDriverplugin. +You can see theWebotsControllernode as the interface that connects your controller plugin to the target robot.my_robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path},])After that, the two nodes are set to be launched in theLaunchDescriptionconstructor:returnLaunchDescription([webots,my_robot_driver,Finally, an optional part is added in order to shutdown all the nodes once Webots terminates (e.g., when it gets closed from the graphical user interface).launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))NoteMore details onWebotsControllerandWebotsLauncherarguments can be foundon the nodes reference page.6 Edit additional filesPythonC++Before you can start the launch file, you have to modify thesetup.pyfile to include the extra files you added. +Openmy_package/setup.pyand replace its contents with:fromsetuptoolsimportfind_packages,setuppackage_name='my_package'data_files=[]data_files.append(('share/ament_index/resource_index/packages',['resource/'+package_name]))data_files.append(('share/'+package_name+'/launch',['launch/robot_launch.py']))data_files.append(('share/'+package_name+'/worlds',['worlds/my_world.wbt']))data_files.append(('share/'+package_name+'/resource',['resource/my_robot.urdf']))data_files.append(('share/'+package_name,['package.xml']))setup(name=package_name,version='0.0.0',packages=find_packages(exclude=['test']),data_files=data_files,install_requires=['setuptools'],zip_safe=True,maintainer='user',maintainer_email='user.name@mail.com',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts':['my_robot_driver = my_package.my_robot_driver:main',],},)This sets-up the package and adds in thedata_filesvariable the newly added files:my_world.wbt,my_robot.urdfandrobot_launch.py.Before you can start the launch file, you have to modifyCMakeLists.txtandmy_robot_driver.xmlfiles:CMakeLists.txtdefines the compilation rules of your plugin.my_robot_driver.xmlis necessary for the pluginlib to find your Webots ROS 2 plugin.Openmy_package/my_robot_driver.xmland replace its contents with:ThisisaWebotsROS2pluginexampleOpenmy_package/CMakeLists.txtand replace its contents with:cmake_minimum_required(VERSION3.5)project(my_package)if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD14)endif()# Besides the package specific dependencies we also need the `pluginlib` and `webots_ros2_driver`find_package(ament_cmakeREQUIRED)find_package(rclcppREQUIRED)find_package(std_msgsREQUIRED)find_package(geometry_msgsREQUIRED)find_package(pluginlibREQUIRED)find_package(webots_ros2_driverREQUIRED)# Export the plugin configuration filepluginlib_export_plugin_description_file(webots_ros2_drivermy_robot_driver.xml)# MyRobotDriver libraryadd_library(${PROJECT_NAME}SHAREDsrc/MyRobotDriver.cpp)target_include_directories(${PROJECT_NAME}PRIVATEinclude)ament_target_dependencies(${PROJECT_NAME}pluginlibrclcppwebots_ros2_driver)install(TARGETS${PROJECT_NAME}ARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)# Install additional directories.install(DIRECTORYlaunchresourceworldsDESTINATIONshare/${PROJECT_NAME}/)ament_export_include_directories(include)ament_export_libraries(${PROJECT_NAME})ament_package()The CMakeLists.txt exports the plugin configuration file with thepluginlib_export_plugin_description_file(), defines a shared library of the C++ pluginsrc/MyRobotDriver.cpp, and sets the include and library dependencies usingament_target_dependencies().The file then installs the library, the directorieslaunch,resource, andworldsto theshare/my_packagedirectory. +Finally, it exports the include directories and libraries usingament_export_include_directories()andament_export_libraries(), respectively, and declares the package usingament_package().7 Test the codeLinuxWindowsmacOSFrom a terminal in your ROS 2 workspace run:colcon buildsource install/local_setup.bashros2 launch my_package robot_launch.pyThis will launch the simulation. +Webots will be automatically installed on the first run in case it was not already installed.From a terminal in your WSL ROS 2 workspace run:colcon buildexport WEBOTS_HOME=/mnt/c/Program\ Files/Webotssource install/local_setup.bashros2 launch my_package robot_launch.pyBe sure to use the/mntprefix in front of your path to the Webots installation folder to access the Windows file system from WSL.This will launch the simulation. +Webots will be automatically installed on the first run in case it was not already installed.On macOS, a local server must be started on the host to start Webots from the VM. +The local server can be downloadedon the webots-server repository.In a terminal of the host machine (not in the VM), specify the Webots installation folder (e.g./Applications/Webots.app) and start the server using the following commands:export WEBOTS_HOME=/Applications/Webots.apppython3 local_simulation_server.pyFrom a terminal in the Linux VM in your ROS 2 workspace, build and launch your custom package with:colcon buildsource install/local_setup.bashros2 launch my_package robot_launch.pyNoteIf you want to install Webots manually, you can download ithere.Then, open a second terminal and send a command with:ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: { x: 0.1 }"The robot is now moving forward.At this point, the robot is able to blindly follow your motor commands. +But it will eventually bump into the wall as you order it to move forwards.Close the Webots window, this should also shutdown your ROS nodes started from the launcher. +Close also the topic command withCtrl+Cin the second terminal.SummaryIn this tutorial, you set-up a realistic robot simulation with Webots and implemented a custom plugin to control the motors of the robot.Next stepsTo improve the simulation, the robot’s sensors can be used to detect obstacles and avoid them. +The second part of the tutorial shows how to implement such behaviour:Setting up a robot simulation (Advanced). + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 --node-name my_robot_driver my_package --dependencies rclpy geometry_msgs webots_ros2_driver + +Language: unknown +cd my_packagemkdir launchmkdir worlds + +Language: unknown +src/└── my_package/├── launch/├── my_package/│ ├── __init__.py│ └── my_robot_driver.py├── resource/│ └── my_package├── test/│ ├── test_copyright.py│ ├── test_flake8.py│ └── test_pep257.py├── worlds/├── package.xml├── setup.cfg└── setup.py + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 --node-name MyRobotDriver my_package --dependencies rclcpp geometry_msgs webots_ros2_driver pluginlib + +Language: unknown +cd my_packagemkdir launchmkdir worldsmkdir resource + +Language: unknown +touch my_robot_driver.xmltouch include/my_package/MyRobotDriver.hpp + +Language: unknown +src/└── my_package/├── include/│ └── my_package/│ └── MyRobotDriver.hpp├── launch/├── resource/├── src/│ └── MyRobotDriver.cpp├── worlds/├── CMakeList.txt├── my_robot_driver.xml└── package.xml + +Language: unknown +importrclpyfromgeometry_msgs.msgimportTwistHALF_DISTANCE_BETWEEN_WHEELS=0.045WHEEL_RADIUS=0.025classMyRobotDriver:definit(self,webots_node,properties):self.__robot=webots_node.robotself.__left_motor=self.__robot.getDevice('left wheel motor')self.__right_motor=self.__robot.getDevice('right wheel motor')self.__left_motor.setPosition(float('inf'))self.__left_motor.setVelocity(0)self.__right_motor.setPosition(float('inf'))self.__right_motor.setVelocity(0)self.__target_twist=Twist()rclpy.init(args=None)self.__node=rclpy.create_node('my_robot_driver')self.__node.create_subscription(Twist,'cmd_vel',self.__cmd_vel_callback,1)def__cmd_vel_callback(self,twist):self.__target_twist=twistdefstep(self):rclpy.spin_once(self.__node,timeout_sec=0)forward_speed=self.__target_twist.linear.xangular_speed=self.__target_twist.angular.zcommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUScommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUSself.__left_motor.setVelocity(command_motor_left)self.__right_motor.setVelocity(command_motor_right) + +Language: unknown +definit(self,webots_node,properties):self.__robot=webots_node.robotself.__left_motor=self.__robot.getDevice('left wheel motor')self.__right_motor=self.__robot.getDevice('right wheel motor')self.__left_motor.setPosition(float('inf'))self.__left_motor.setVelocity(0)self.__right_motor.setPosition(float('inf'))self.__right_motor.setVelocity(0)self.__target_twist=Twist()rclpy.init(args=None)self.__node=rclpy.create_node('my_robot_driver')self.__node.create_subscription(Twist,'cmd_vel',self.__cmd_vel_callback,1) + +Language: unknown +def__cmd_vel_callback(self,twist):self.__target_twist=twist + +Language: unknown +defstep(self):rclpy.spin_once(self.__node,timeout_sec=0)forward_speed=self.__target_twist.linear.xangular_speed=self.__target_twist.angular.zcommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUScommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUSself.__left_motor.setVelocity(command_motor_left)self.__right_motor.setVelocity(command_motor_right) + +Language: unknown +#ifndef WEBOTS_ROS2_PLUGIN_EXAMPLE_HPP#define WEBOTS_ROS2_PLUGIN_EXAMPLE_HPP#include"rclcpp/macros.hpp"#include"webots_ros2_driver/PluginInterface.hpp"#include"webots_ros2_driver/WebotsNode.hpp"#include"geometry_msgs/msg/twist.hpp"#include"rclcpp/rclcpp.hpp"namespacemy_robot_driver{classMyRobotDriver:publicwebots_ros2_driver::PluginInterface{public:voidstep()override;voidinit(webots_ros2_driver::WebotsNode*node,std::unordered_map¶meters)override;private:rclcpp::Subscription::SharedPtrcmd_vel_subscription_;geometry_msgs::msg::Twistcmd_vel_msg;WbDeviceTagright_motor;WbDeviceTagleft_motor;};}// namespace my_robot_driver#endif + +Language: unknown +#include"my_package/MyRobotDriver.hpp"#include"rclcpp/rclcpp.hpp"#include#include#include#include#define HALF_DISTANCE_BETWEEN_WHEELS 0.045#define WHEEL_RADIUS 0.025namespacemy_robot_driver{voidMyRobotDriver::init(webots_ros2_driver::WebotsNode*node,std::unordered_map¶meters){right_motor=wb_robot_get_device("right wheel motor");left_motor=wb_robot_get_device("left wheel motor");wb_motor_set_position(left_motor,INFINITY);wb_motor_set_velocity(left_motor,0.0);wb_motor_set_position(right_motor,INFINITY);wb_motor_set_velocity(right_motor,0.0);cmd_vel_subscription_=node->create_subscription("/cmd_vel",rclcpp::SensorDataQoS().reliable(),[this](constgeometry_msgs::msg::Twist::SharedPtrmsg){this->cmd_vel_msg.linear=msg->linear;this->cmd_vel_msg.angular=msg->angular;});}voidMyRobotDriver::step(){autoforward_speed=cmd_vel_msg.linear.x;autoangular_speed=cmd_vel_msg.angular.z;autocommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;autocommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;wb_motor_set_velocity(left_motor,command_motor_left);wb_motor_set_velocity(right_motor,command_motor_right);}}// namespace my_robot_driver#include"pluginlib/class_list_macros.hpp"PLUGINLIB_EXPORT_CLASS(my_robot_driver::MyRobotDriver,webots_ros2_driver::PluginInterface) + +Language: unknown +voidMyRobotDriver::init(webots_ros2_driver::WebotsNode*node,std::unordered_map¶meters){right_motor=wb_robot_get_device("right wheel motor");left_motor=wb_robot_get_device("left wheel motor");wb_motor_set_position(left_motor,INFINITY);wb_motor_set_velocity(left_motor,0.0);wb_motor_set_position(right_motor,INFINITY);wb_motor_set_velocity(right_motor,0.0);cmd_vel_subscription_=node->create_subscription("/cmd_vel",rclcpp::SensorDataQoS().reliable(),[this](constgeometry_msgs::msg::Twist::SharedPtrmsg){this->cmd_vel_msg.linear=msg->linear;this->cmd_vel_msg.angular=msg->angular;});} + +Language: unknown +[this](constgeometry_msgs::msg::Twist::SharedPtrmsg){this->cmd_vel_msg.linear=msg->linear;this->cmd_vel_msg.angular=msg->angular;} + +Language: unknown +voidMyRobotDriver::step(){autoforward_speed=cmd_vel_msg.linear.x;autoangular_speed=cmd_vel_msg.angular.z;autocommand_motor_left=(forward_speed-angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;autocommand_motor_right=(forward_speed+angular_speed*HALF_DISTANCE_BETWEEN_WHEELS)/WHEEL_RADIUS;wb_motor_set_velocity(left_motor,command_motor_left);wb_motor_set_velocity(right_motor,command_motor_right);} + +Language: unknown +#include"pluginlib/class_list_macros.hpp"PLUGINLIB_EXPORT_CLASS(my_robot_driver::MyRobotDriver,webots_ros2_driver::PluginInterface) + +Language: unknown + + +Language: unknown + + +Language: unknown +someValue + +Language: unknown +someValue + +Language: unknown +importosimportlaunchfromlaunchimportLaunchDescriptionfromament_index_python.packagesimportget_package_share_directoryfromwebots_ros2_driver.webots_launcherimportWebotsLauncherfromwebots_ros2_driver.webots_controllerimportWebotsControllerdefgenerate_launch_description():package_dir=get_package_share_directory('my_package')robot_description_path=os.path.join(package_dir,'resource','my_robot.urdf')webots=WebotsLauncher(world=os.path.join(package_dir,'worlds','my_world.wbt'))my_robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path},])returnLaunchDescription([webots,my_robot_driver,launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))]) + +Language: unknown +webots=WebotsLauncher(world=os.path.join(package_dir,'worlds','my_world.wbt')) + +Language: unknown +my_robot_driver=WebotsController(robot_name='my_robot',parameters=[{'robot_description':robot_description_path},]) + +Language: unknown +returnLaunchDescription([webots,my_robot_driver, + +Language: unknown +launch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],)) + +Language: unknown +fromsetuptoolsimportfind_packages,setuppackage_name='my_package'data_files=[]data_files.append(('share/ament_index/resource_index/packages',['resource/'+package_name]))data_files.append(('share/'+package_name+'/launch',['launch/robot_launch.py']))data_files.append(('share/'+package_name+'/worlds',['worlds/my_world.wbt']))data_files.append(('share/'+package_name+'/resource',['resource/my_robot.urdf']))data_files.append(('share/'+package_name,['package.xml']))setup(name=package_name,version='0.0.0',packages=find_packages(exclude=['test']),data_files=data_files,install_requires=['setuptools'],zip_safe=True,maintainer='user',maintainer_email='user.name@mail.com',description='TODO: Package description',license='TODO: License declaration',tests_require=['pytest'],entry_points={'console_scripts':['my_robot_driver = my_package.my_robot_driver:main',],},) + +Language: unknown +ThisisaWebotsROS2pluginexample + +Language: unknown +cmake_minimum_required(VERSION3.5)project(my_package)if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD14)endif()# Besides the package specific dependencies we also need the `pluginlib` and `webots_ros2_driver`find_package(ament_cmakeREQUIRED)find_package(rclcppREQUIRED)find_package(std_msgsREQUIRED)find_package(geometry_msgsREQUIRED)find_package(pluginlibREQUIRED)find_package(webots_ros2_driverREQUIRED)# Export the plugin configuration filepluginlib_export_plugin_description_file(webots_ros2_drivermy_robot_driver.xml)# MyRobotDriver libraryadd_library(${PROJECT_NAME}SHAREDsrc/MyRobotDriver.cpp)target_include_directories(${PROJECT_NAME}PRIVATEinclude)ament_target_dependencies(${PROJECT_NAME}pluginlibrclcppwebots_ros2_driver)install(TARGETS${PROJECT_NAME}ARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)# Install additional directories.install(DIRECTORYlaunchresourceworldsDESTINATIONshare/${PROJECT_NAME}/)ament_export_include_directories(include)ament_export_libraries(${PROJECT_NAME})ament_package() + +Language: unknown +colcon buildsource install/local_setup.bashros2 launch my_package robot_launch.py + +Language: unknown +colcon buildexport WEBOTS_HOME=/mnt/c/Program\ Files/Webotssource install/local_setup.bashros2 launch my_package robot_launch.py + +Language: unknown +export WEBOTS_HOME=/Applications/Webots.apppython3 local_simulation_server.py + +Language: unknown +colcon buildsource install/local_setup.bashros2 launch my_package robot_launch.py + +Language: unknown +ros2 topic pub /cmd_vel geometry_msgs/Twist "linear: { x: 0.1 }" diff --git "a/exported_docs/ros2/Setting_up_security\357\203\201.txt" "b/exported_docs/ros2/Setting_up_security\357\203\201.txt" new file mode 100644 index 0000000..0e9e12f --- /dev/null +++ "b/exported_docs/ros2/Setting_up_security\357\203\201.txt" @@ -0,0 +1,103 @@ +Title: Setting up security +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Security/Introducing-ros2-security.html +Section: Installation +-------------------------------------------------------------------------------- + +Setting up securityGoal:Set up security withsros2.Tutorial level:AdvancedTime:15 minutesContentsBackgroundInstallationInstalling from sourceSelecting an alternate middlewareRun the demo1. Create a folder for the security files2. Generate a keystore3. Generate keys and certificates4. Configure environment variables5. Run thetalker/listenerdemoTake the Quiz!Learn More!BackgroundThesros2package provides the tools and instructions to use ROS 2 on top of DDS-Security. +The security features have been tested across platforms (Linux, macOS, and Windows) as well as across different languages (C++ and Python). +The SROS2 has been designed to work with any secure middleware, although not all middleware is open source and support varies depending on the ROS distribution in use.InstallationTypically security is available following installation using theROS 2 Installation Guideand theconfiguration guide. +However, if you intend to install from source or switch middleware implementations, consider the following caveats:Installing from sourceBefore installing from source, you will need to have a recent version openssl (1.0.2g or later) installed:LinuxMacOSWindowssudoaptupdate +sudoaptinstalllibssl-devbrewinstallopensslYou will need to have OpenSSL on your library path to run DDS-Security demos. +Run the following command, and consider adding to your~/.bash_profile:exportDYLD_LIBRARY_PATH=`brew--prefixopenssl`/lib:$DYLD_LIBRARY_PATHexportOPENSSL_ROOT_DIR=`brew--prefixopenssl`If you don’t have OpenSSL installed, please followthese instructionsFast DDS requires an additional CMake flag to build the security plugins, so the colcon invocation needs to be modified to pass:colconbuild--symlink-install--cmake-args-DSECURITY=ONSelecting an alternate middlewareIf you choose not to use the default middleware implementation, be sure tochange your DDS implementationbefore proceeding.ROS 2 allows you to change the DDS implementation at runtime. +Seehow to work with mulitple RMW implementationsto explore different middleware implementations.Note that secure communication between vendors is not supported.Run the demo1. Create a folder for the security filesBegin by creating folder to store all the files necessary for this demo:LinuxMacOSWindowsmkdir~/sros2_demomkdir~/sros2_demomdC:\dev\ros2\sros2_demo2. Generate a keystoreUse thesros2utilities to create the keystore. +Files in the keystore will be used to enable security for all the participants in the ROS 2 graph.LinuxMacOSWindowscd~/sros2_demo +ros2securitycreate_keystoredemo_keystorecd~/sros2_demo +ros2securitycreate_keystoredemo_keystorecdsros2_demo +ros2 security create_keystore demo_keystore3. Generate keys and certificatesOnce the keystore is created, create keys and certificates for each node with security enabled. +For our demo, that includes the talker and listener nodes. +This command uses thecreate_enclavefeature which is covered in more detail in the next tutorial.LinuxMacOSWindowsros2securitycreate_enclavedemo_keystore/talker_listener/talker +ros2securitycreate_enclavedemo_keystore/talker_listener/listenerros2securitycreate_enclavedemo_keystore/talker_listener/talker +ros2securitycreate_enclavedemo_keystore/talker_listener/listenerros2 security create_enclave demo_keystore /talker_listener/talker +ros2 security create_enclave demo_keystore /talker_listener/listenerIfunabletowrite'randomstate'appears then set the environment variableRANDFILE.setRANDFILE=C:\dev\ros2\sros2_demo\.rndThen re-run the commands above.4. Configure environment variablesThree environment variables allow the middleware to locate encryption materials and enable (and possibly enforce) security. +These and other security-related environment variables are described in theROS 2 DDS-Security Integration design document.LinuxMacOSWindowsexportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=EnforceexportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=EnforcesetROS_SECURITY_KEYSTORE=%cd%/demo_keystoresetROS_SECURITY_ENABLE=truesetROS_SECURITY_STRATEGY=EnforceThese variables need to be defined in each terminal used for the demo. +For convenience you can add them to your boot environment.5. Run thetalker/listenerdemoBegin the demo by launching the talker node.ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talkerIn another terminal, do the same to launch thelistenernode. +The environment variables in this terminal must be properly set as described in step 4 above.ros2rundemo_nodes_pylistener--ros-args--enclave/talker_listener/listenerThese nodes will be communicating using authentication and encryption! +If you look at the packet contents (for example, usingtcpdumporWiresharkas covered in another tutorial), you can see that the messages are encrypted.Note: You can switch between the C++ (demo_nodes_cpp) and Python (demo_nodes_py) packages arbitrarily.These nodes are able to communicate because we have created the appropriate keys and certificates for them.Leave both nodes running as you answer the questions below.Take the Quiz!Question 1Answer 1Open another terminal session, butdo notset the environment variables so that security is not enabled. +Start the listener. +What do you expect to happen?The listener launches but does not receive any messages. +All traffic is encrypted, and without security enabled the listener does not receive anything.Question 2Answer 2Stop the listener, set the environment variableROS_SECURITY_ENABLEtotrueand start the listener again. +What results do you expect this time?The listener still launches but does not receive messages. +Although security has now been enabled, it is not been configured properly since ROS is unable to locate the key files. +The listener launches, but in non-secure mode since security is not enforced, which means that although the properly configured talker is sending encrypted messages, this listener is unable to decrypt them.Question 3Answer 3Stop the listener and setROS_SECURITY_STRATEGYtoEnforce. +What happens now?The listener fails to launch. +Security has been enabled and is being enforced. +Since it still is not properly configured, an error is thrown rather than launching in non-secure mode.Learn More!Are you ready to go further with ROS Security? +Take a look at theSecure Turtlebot2 Demo. +You’ll find a functioning and complex implementation of ROS 2 security, ready to try out your own custom scenarios. +Be sure to create pull requests and issues here so we can continue improving security support in ROS! + +Code Examples: + +Language: unknown +sudoaptupdate +sudoaptinstalllibssl-dev + +Language: unknown +brewinstallopenssl + +Language: unknown +exportDYLD_LIBRARY_PATH=`brew--prefixopenssl`/lib:$DYLD_LIBRARY_PATHexportOPENSSL_ROOT_DIR=`brew--prefixopenssl` + +Language: unknown +colconbuild--symlink-install--cmake-args-DSECURITY=ON + +Language: unknown +mkdir~/sros2_demo + +Language: unknown +mkdir~/sros2_demo + +Language: unknown +mdC:\dev\ros2\sros2_demo + +Language: unknown +cd~/sros2_demo +ros2securitycreate_keystoredemo_keystore + +Language: unknown +cd~/sros2_demo +ros2securitycreate_keystoredemo_keystore + +Language: unknown +cdsros2_demo +ros2 security create_keystore demo_keystore + +Language: unknown +ros2securitycreate_enclavedemo_keystore/talker_listener/talker +ros2securitycreate_enclavedemo_keystore/talker_listener/listener + +Language: unknown +ros2securitycreate_enclavedemo_keystore/talker_listener/talker +ros2securitycreate_enclavedemo_keystore/talker_listener/listener + +Language: unknown +ros2 security create_enclave demo_keystore /talker_listener/talker +ros2 security create_enclave demo_keystore /talker_listener/listener + +Language: unknown +setRANDFILE=C:\dev\ros2\sros2_demo\.rnd + +Language: unknown +exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforce + +Language: unknown +exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforce + +Language: unknown +setROS_SECURITY_KEYSTORE=%cd%/demo_keystoresetROS_SECURITY_ENABLE=truesetROS_SECURITY_STRATEGY=Enforce + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker + +Language: unknown +ros2rundemo_nodes_pylistener--ros-args--enclave/talker_listener/listener diff --git "a/exported_docs/ros2/Simulators\357\203\201.txt" "b/exported_docs/ros2/Simulators\357\203\201.txt" new file mode 100644 index 0000000..9673029 --- /dev/null +++ "b/exported_docs/ros2/Simulators\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Simulators +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Simulation-Main.html +Section: Installation +-------------------------------------------------------------------------------- + +SimulatorsSeveral advanced robot simulators can be used with ROS 2, such as Gazebo, Webots, etc. +Unlike turtlesim, they provide fairly realistic results relying on physics-based models for robots, sensors, actuators and objects. +Hence, what you observe in simulation is very close to what you will get when transferring your ROS 2 controllers to a real robot.This set of tutorials will teach you how to configure different simulators with ROS 2.WebotsGazebo \ No newline at end of file diff --git "a/exported_docs/ros2/Subsequent_Releases\357\203\201.txt" "b/exported_docs/ros2/Subsequent_Releases\357\203\201.txt" new file mode 100644 index 0000000..b716215 --- /dev/null +++ "b/exported_docs/ros2/Subsequent_Releases\357\203\201.txt" @@ -0,0 +1,52 @@ +Title: Subsequent Releases +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Releasing/Subsequent-Releases.html +Section: Installation +-------------------------------------------------------------------------------- + +Subsequent ReleasesThis guide explains how to release new versions of ROS packages that have already been released before.Table of ContentsBe part of the release teamInstall dependenciesSet up a Personal Access TokenEnsure repositories are up-to-dateUpdating ChangelogBump the package versionBloom ReleaseNext StepsBe part of the release teamIf you are not part of the release team that has write access to the release repository, followJoin a release team.Install dependenciesInstall tools that you will use in the upcoming steps according to your platform:deb (eg. Ubuntu)RPM (eg. RHEL)Othersudoaptinstallpython3-bloompython3-catkin-pkgsudodnfinstallpython3-bloompython3-catkin_pkgpip3install-Ubloomcatkin_pkgMake sure you have rosdep initialized:sudorosdepinit +rosdepupdateNote that therosdepinitcommand may fail if it has already been initialized in the past; this can safely be ignored.Set up a Personal Access TokenWarningIf the file~/.config/bloomexists on your computer, it is likely that you have done this before so you should skip this section.During the release process, multiple HTTPS Git operations will be performed that require password authentication. +To avoid being repeatedly asked for a password, aPersonal Access Token (PAT)will be set up. +If you have multi-factor authentication setup on your GitHub account, youmustsetup a Personal Access Token.Create a Personal Access Token by:Log in to GitHub and go toPersonal access tokens.Click theGenerate new tokenbutton.In the dropdown, selectGenerate new token (classic)SetNoteto something likeBloomtoken.SetExpirationtoNo expiration.Tick thepublic_repoandworkflowcheckboxes.Click theGenerate tokenbutton.After you have created the token, you will end up back at thePersonal access tokenspage.Copy the alphanumeric tokenthat is highlighted in green.Save your GitHub username and PAT to a new file called~/.config/bloom, with the format below:{ + "github_user": "", + "oauth_token": "" +}Ensure repositories are up-to-dateMake sure that:Your repository is hosted on a remote such as GitHub.You have a clone of the repository on your computer and are on the right branch.Both the remote repository and your clone are up-to-date.Updating ChangelogFor your users and for the developers, keep the changelog concise and up to date.catkin_generate_changelogOpen allCHANGELOG.rstfiles in an editor. +You will see thatcatkin_generate_changeloghas auto-generated a forthcoming section with notes from commit messages:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Changelog for package your_package^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Forthcoming-----------*you can modify this commit message*and thisClean up the list of commit messages to concisely convey the notable changes that have been made to the packages since the last release, andcommit all the CHANGELOG.rst files.Do not modify theForthcomingheader.Bump the package versionEvery release of the package must have a unique version number higher than the previous release. +Run:catkin_prepare_releasewhich performs the following:increases the package version inpackage.xmlreplaces the headingForthcomingwithversion(date)(eg.0.0.1(2022-01-08)) inCHANGELOG.rstcommits those changescreates a tag (eg.0.0.1)pushes the changes and the tag to your remote repositoryNoteBy default the patch version of the package is incremented, such as from0.0.0to0.0.1. +To increment the minor or major version instead, runcatkin_prepare_release--bumpminororcatkin_prepare_release--bumpmajor. +For more details, seecatkin_prepare_release--help.Bloom ReleaseRun the following command, replacingmy_repowith the name of your repository with the packages:bloom-release--rosdistrojazzymy_repoBloom will automatically create a pull request for you againstrosdistro.Next StepsOnce your pull request has been submitted, usually within one or two days, one of the maintainers of rosdistro will review and merge your Pull Request. +If your package build is successful, in 24-48 hours your packages will become available in theros-testingrepository, where you cantest your pre-release binaries.Approximately every two to four weeks, the distribution’s release manager manually synchronizes the contents of ros-testing into the main ROS repository. +This is when your packages actually become available to the rest of the ROS community. +To get updates on when the next synchronization (sync) is coming, subscribe to thePackaging and Release Management Category on ROS Discourse. + +Code Examples: + +Language: unknown +sudoaptinstallpython3-bloompython3-catkin-pkg + +Language: unknown +sudodnfinstallpython3-bloompython3-catkin_pkg + +Language: unknown +pip3install-Ubloomcatkin_pkg + +Language: unknown +sudorosdepinit +rosdepupdate + +Language: unknown +{ + "github_user": "", + "oauth_token": "" +} + +Language: unknown +catkin_generate_changelog + +Language: unknown +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Changelog for package your_package^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Forthcoming-----------*you can modify this commit message*and this + +Language: unknown +catkin_prepare_release + +Language: unknown +bloom-release--rosdistrojazzymy_repo diff --git "a/exported_docs/ros2/Synchronous_vs._asynchronous_service_clients\357\203\201.txt" "b/exported_docs/ros2/Synchronous_vs._asynchronous_service_clients\357\203\201.txt" new file mode 100644 index 0000000..dc4a526 --- /dev/null +++ "b/exported_docs/ros2/Synchronous_vs._asynchronous_service_clients\357\203\201.txt" @@ -0,0 +1,34 @@ +Title: Synchronous vs. asynchronous service clients +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Sync-Vs-Async.html +Section: Installation +-------------------------------------------------------------------------------- + +Synchronous vs. asynchronous service clientsLevel:IntermediateTime:10 minutesContentsIntroduction1 Synchronous calls1.1 Sync deadlock2 Asynchronous callsSummaryIntroductionThis guide is intended to warn users of the risks associated with the Python synchronous service clientcall()API. +It is very easy to mistakenly cause deadlock when calling services synchronously, so we do not recommend usingcall().We provide an example on how to usecall()correctly for experienced users who wish to use synchronous calls and are aware of the pitfalls. +We also highlight possible scenarios for deadlock that accompany it.Because we recommend avoiding sync calls, this guide will also address the features and usage of the recommended alternative, async calls (call_async()).The C++ service call API is only available in async, so the comparisons and examples in this guide pertain to Python services and clients. +The definition of async given here generally applies to C++, with some exceptions.1 Synchronous callsA synchronous client will block the calling thread when sending a request to a service until a response has been received; nothing else can happen on that thread during the call. +The call can take arbitrary amounts of time to complete. +Once complete, the response returns directly to the client.The following is an example of how to correctly execute a synchronous service call from a client node, similar to the async node in theSimple Service and Clienttutorial.importsysfromthreadingimportThreadfromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeclassMinimalClientSync(Node):def__init__(self):super().__init__('minimal_client_sync')self.cli=self.create_client(AddTwoInts,'add_two_ints')whilenotself.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req=AddTwoInts.Request()defsend_request(self):self.req.a=int(sys.argv[1])self.req.b=int(sys.argv[2])returnself.cli.call(self.req)# This only works because rclpy.spin() is called in a separate thread below.# Another configuration, like spinning later in main() or calling this method from a timer callback, would result in a deadlock.defmain():rclpy.init()minimal_client=MinimalClientSync()spin_thread=Thread(target=rclpy.spin,args=(minimal_client,))spin_thread.start()response=minimal_client.send_request()minimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(minimal_client.req.a,minimal_client.req.b,response.sum))minimal_client.destroy_node()rclpy.shutdown()if__name__=='__main__':main()Note insidemain()that the client callsrclpy.spinin a separate thread. +Bothsend_requestandrclpy.spinare blocking, so they need to be on separate threads.1.1 Sync deadlockThere are several ways that the synchronouscall()API can cause deadlock.As mentioned in the comments of the example above, failing to create a separate thread to spinrclpyis one cause of deadlock. +When a client is blocking a thread waiting for a response, but the response can only be returned on that same thread, the client will never stop waiting, and nothing else can happen.Another cause of deadlock is blockingrclpy.spinby calling a service synchronously in a subscription, timer callback or service callback. +For example, if the synchronous client’ssend_requestis placed in a callback:deftrigger_request(msg):response=minimal_client.send_request()# This will cause deadlockminimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(minimal_client.req.a,minimal_client.req.b,response.sum))subscription=minimal_client.create_subscription(String,'trigger',trigger_request,10)rclpy.spin(minimal_client)Deadlock occurs becauserclpy.spinwill not preempt the callback with thesend_requestcall. +In general, callbacks should only perform light and fast operations.WarningWhen deadlock occurs, you will not receive any indication that the service is blocked. +There will be no warning or exception thrown, no indication in the stack trace, and the call will not fail.2 Asynchronous callsAsync calls inrclpyare entirely safe and the recommended method of calling services. +They can be made from anywhere without running the risk of blocking other ROS and non-ROS processes, unlike sync calls.An asynchronous client will immediately returnfuture, a value that indicates whether the call and response is finished (not the value of the response itself), after sending a request to a service. +The returnedfuturemay be queried for a response at any time.Since sending a request doesn’t block anything, a loop can be used to both spinrclpyand checkfuturein the same thread, for example:whilerclpy.ok():rclpy.spin_once(node)iffuture.done():#Get responseTheSimple Service and Clienttutorial for Python illustrates how to perform an async service call and retrieve thefutureusing a loop.Thefuturecan also be retrieved using a timer or callback, like inthis example, a dedicated thread, or by another method. +It is up to you, as the caller, to decide how to storefuture, check on its status, and retrieve your response.SummaryIt is not recommended to implement a synchronous service client. +They are susceptible to deadlock, but will not provide any indication of issue when deadlock occurs. +If you must use synchronous calls, the example in section1 Synchronous callsis a safe method of doing so. +You should also be aware of the conditions that cause deadlock outlined in section1.1 Sync deadlock. +We recommend using async service clients instead. + +Code Examples: + +Language: unknown +importsysfromthreadingimportThreadfromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeclassMinimalClientSync(Node):def__init__(self):super().__init__('minimal_client_sync')self.cli=self.create_client(AddTwoInts,'add_two_ints')whilenotself.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req=AddTwoInts.Request()defsend_request(self):self.req.a=int(sys.argv[1])self.req.b=int(sys.argv[2])returnself.cli.call(self.req)# This only works because rclpy.spin() is called in a separate thread below.# Another configuration, like spinning later in main() or calling this method from a timer callback, would result in a deadlock.defmain():rclpy.init()minimal_client=MinimalClientSync()spin_thread=Thread(target=rclpy.spin,args=(minimal_client,))spin_thread.start()response=minimal_client.send_request()minimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(minimal_client.req.a,minimal_client.req.b,response.sum))minimal_client.destroy_node()rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +deftrigger_request(msg):response=minimal_client.send_request()# This will cause deadlockminimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(minimal_client.req.a,minimal_client.req.b,response.sum))subscription=minimal_client.create_subscription(String,'trigger',trigger_request,10)rclpy.spin(minimal_client) + +Language: unknown +whilerclpy.ok():rclpy.spin_once(node)iffuture.done():#Get response diff --git "a/exported_docs/ros2/Testing_Your_Code_with_the_ROS_Build_Farm\357\203\201.txt" "b/exported_docs/ros2/Testing_Your_Code_with_the_ROS_Build_Farm\357\203\201.txt" new file mode 100644 index 0000000..9a68121 --- /dev/null +++ "b/exported_docs/ros2/Testing_Your_Code_with_the_ROS_Build_Farm\357\203\201.txt" @@ -0,0 +1,7 @@ +Title: Testing Your Code with the ROS Build Farm +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Testing/BuildFarmTesting.html +Section: Installation +-------------------------------------------------------------------------------- + +Testing Your Code with the ROS Build FarmTheROS 2 Build Farmis incredibly powerful. +In addition to creating binaries, it will also test pull requests by compiling and running all the tests for your ROS packages before the PR is merged.There are four prerequisites.The GitHub user@ros-pull-request-buildermust have access to the repository.The GitHub repository must have the webhooks set up.Your package must be indexed in rosdistroThetest_pull_requestsflag must be true.GitHub AccessYou can give access to the PR Builder either at the GitHub organization level OR just to the single GitHub repository.GitHub OrganizationOpenhttps://github.com/orgs/%YOUR_ORG%/people(while replacing%YOUR_ORG%with the appropriate organization)ClickInviteMemberand enterros-pull-request-builderGitHub RepositoryOpenhttps://github.com/%YOUR_ORG%/%YOUR_REPO%/settings/access(while replacing%YOUR_ORG%/%YOUR_REPO$with the appropriate organization/repo)ClickAddpeopleand enterros-pull-request-builderSelectAdminorWritefor their role. (see next section)WebHooksIf you grant full administrative rights toros-pull-request-builder, it will automatically setup the hooks.Alternatively, you can avoid the need for full administrative rights by setting them up with onlywritepermissions.Openhttps://github.com/%YOUR_ORG%/%YOUR_REPO%/settings/hooks/new)Enter"https://build.ros2.org/ghprbhook/as the Payload URLCheck the following options:Let me select individual events.Issue commentsPull requeststest_pull_requestsFor each ROS distro that you want pull request testing for, you must enable thetest_pull_requestsflag in the appropriate section of therosdistro.Option 1- You have the option when runningbloomto turn on pull request testing.Option 2- You cancarefullymanually edit the appropriate file in the rosdistro repo, and make a new pull request.Example.Documented in REP 143.Note that after the pull request has been added, the job will usually not be created until the nightly Jenkins reconfiguration. \ No newline at end of file diff --git "a/exported_docs/ros2/Testing_with_pre-release_binaries\357\203\201.txt" "b/exported_docs/ros2/Testing_with_pre-release_binaries\357\203\201.txt" new file mode 100644 index 0000000..91acf6c --- /dev/null +++ "b/exported_docs/ros2/Testing_with_pre-release_binaries\357\203\201.txt" @@ -0,0 +1,46 @@ +Title: Testing with pre-release binaries +URL: https://docs.ros.org/en/jazzy/Installation/Testing.html +Section: Installation +-------------------------------------------------------------------------------- + +Testing with pre-release binariesMany ROS packages are provided as pre-built binaries. +Usually, you will get the released version of binaries when followingInstallation. +There are also pre-released versions of binaries that are useful for testing before making an official release. +This article describes several options if you would like to try out pre-released versions of ROS binaries.deb testing repositoryWhen packages are released into a ROS distribution (using bloom), the buildfarm builds them into deb packages which are stored temporarily in thebuildingapt repository. +As dependent packages are rebuilt, an automatic process periodically synchronizes the packages inbuildingto a secondary repository calledros-testing.ros-testingis intended as a soaking area where developers and bleeding-edge users may give the packages extra testing, before they are manually synced into the public ros repository from which users typically install packages.Approximately every two weeks, the rosdistro’s release manager manually synchronizes the contents ofros-testinginto themainROS repository.For Debian-based operating systems, you can install binary packages from theros-testingrepository.Make sure you have a working ROS 2 installation from deb packages (seeInstallation).Edit (with sudo) the file/etc/apt/sources.list.d/ros2.listand changeros2withros2-testing. +For example, on Ubuntu Noble the contents should look like the following:# deb http://packages.ros.org/ros2/ubuntu noble maindebhttp://packages.ros.org/ros2-testing/ubuntunoblemainUpdate theaptindex:sudoaptupdateYou can now install individual packages from the testing repository, for example:sudoaptinstallros-jazzy-my-just-released-packageAlternatively, you can move your entire ROS 2 installation to the testing repository:sudoaptdist-upgradeOnce you are finished testing, you can switch back to the normal repository by changing back the contents of/etc/apt/sources.list.d/ros2.list:debhttp://packages.ros.org/ros2/ubuntunoblemain# deb http://packages.ros.org/ros2-testing/ubuntu noble mainand doing an update and upgrade:sudoaptupdate +sudoaptdist-upgradeBinary archivesFor core packages, we run nightly packaging jobs for Ubuntu Linux, RHEL, and Windows. +These packaging jobs produce archives with pre-built binaries that can be downloaded and extracted to your filesystem.Make sure you have all dependencies installed according to thelatest development setupfor your platform.Go tohttps://ci.ros2.org/view/packaging/and select a packaging job from the list corresponding to your platform.Under the heading “Last Successful Artifacts” you should see a download link (e.g. for Windows,ros2-package-windows-AMD64.zip).Download and extract the archive to your file system.To use the binary archive installation, source thesetup.*file that can be found in the root of the archive.Ubuntu Linux and RHELWindowssourcepath/to/extracted/archive/setup.bashcallpath\to\extracted\archive\setup.batDockerFor Ubuntu Linux, there is also a nightly Docker image based on the nightly binary archive.Pull the Docker image:dockerpullosrf/ros2:nightlyStart an interactive container:dockerrun-itosrf/ros2:nightlyFor support on running GUI applications in Docker, take a look at the tutorialUser GUI’s with Dockeror the toolrocker. + +Code Examples: + +Language: unknown +# deb http://packages.ros.org/ros2/ubuntu noble maindebhttp://packages.ros.org/ros2-testing/ubuntunoblemain + +Language: unknown +sudoaptupdate + +Language: unknown +sudoaptinstallros-jazzy-my-just-released-package + +Language: unknown +sudoaptdist-upgrade + +Language: unknown +debhttp://packages.ros.org/ros2/ubuntunoblemain# deb http://packages.ros.org/ros2-testing/ubuntu noble main + +Language: unknown +sudoaptupdate +sudoaptdist-upgrade + +Language: unknown +sourcepath/to/extracted/archive/setup.bash + +Language: unknown +callpath\to\extracted\archive\setup.bat + +Language: unknown +dockerpullosrf/ros2:nightly + +Language: unknown +dockerrun-itosrf/ros2:nightly diff --git "a/exported_docs/ros2/Testing\357\203\201.txt" "b/exported_docs/ros2/Testing\357\203\201.txt" new file mode 100644 index 0000000..b2b0746 --- /dev/null +++ "b/exported_docs/ros2/Testing\357\203\201.txt" @@ -0,0 +1,10 @@ +Title: Testing +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Testing/Testing-Main.html +Section: Installation +-------------------------------------------------------------------------------- + +TestingWhy automatic tests?Here are some of the many good reasons why should we have automated tests:You can make incremental updates to your code more quickly. ROS has hundreds of packages with many interdependencies, so it can be hard to anticipate the problems a small change might cause. If your change passes the unit tests, you can be more confident that you haven’t introduced problems — or at least the problems aren’t your fault.You can refactor your code with greater confidence. Passing the unit tests verifies that you haven’t introduced any bugs while refactoring. This gives you this wonderful freedom from change fear!It leads to better designed code. Unit tests force you to write your code so that it can be more easily tested. This often means keeping your underlying functions and framework separate, which is one of our design goals with ROS code.They prevent recurring bugs (bug regressions). It’s a good practice to write a unit test for every bug you fix. In fact, write the unit test before you fix the bug. This will help you to precisely, or even deterministically, reproduce the bug, and much more precisely understand what the problem is. As a result, you will also create a better patch, which you can then test with your regression test to verify that the bug is fixed. That way the bug won’t accidentally get reintroduced if the code gets modified later on. It also means that it will be easier to convince the reviewer of the patch that the problem is solved, and the contribution is of high quality.Other people can work on your code more easily (an automatic form of documentation). It can be hard to figure out whether or not you’ve broken someone else’s code when you make a change. The unit tests are a tool for other developers to validate their changes. Automatic tests document your coding decisions, and communicate to other developers automatically about their violation. Thus tests become documentation for your code — a documentation that does not need to be read for the most time, and when it does need to be inspected the test system will precisely indicate what to read (which tests fail). By writing automatic tests you make other contributors faster. This improves the entire ROS project.It is much easier to become a contributor to ROS if we have automated unit tests. It is very difficult for new external developers to contribute to your components. When they make changes to code, they are often doing it in the blind, driven by a lot of guesswork. By providing a harness of automated tests, you help them in the task. They get immediate feedback for their changes. It becomes easier to contribute to a project, and new contributors to join more easily. Also their first contributions are of higher quality, which decreases the workload on maintainers. A win-win!Automatic tests simplify maintainership. Especially for mature packages, which change more slowly, and mostly need to be updated to new dependencies, an automatic test suite helps to very quickly establish whether the package still works. This makes it much easier to decide whether the package is still supported or not.Automatic tests amplify the value of Continuous Integration. Regression tests, along with normal scenario-based requirements tests, contribute to overall body of automated tests for your component. Your component is better tested against evolution of other APIs that it depends on (CI servers will tell you better and more precisely what problems develop in your code).Perhaps the most important benefit of writing tests is that tests make you a good citizen. +Tests influence quality in the long term. +It is a well accepted practice in many open-source projects. +By writing regressions tests, you are contributing to long term quality of the ROS ecosystem.Is this all coming for free?Of course, there is never free lunch. +To get the benefits of testing, some investment is necessary.You need to develop a test, which sometimes may be difficult or costly. Sometimes it might also be nontrivial, as the test should be automatic. Things get particularly hairy if your tests should involve special hardware (they should not: try to use simulation, mock the hardware, or narrow down the test to a smaller software problem) or require external environment, for instance human operators.Regression tests and other automatic tests need to be maintained. When the design of the component changes, a lot of tests become invalidated (for instance they no longer compile, or throw runtime exceptions related to the API design). These tests fail not only because the redesign re-introduced bugs but also because they need to be updated to the new design. Occasionally, with bigger redesigns, old regression tests should be dropped.Large bodies of tests can take a long time to run, which can increase Continuous Integration server costs.Available Tutorials:Running Tests in ROS 2 from the Command LineWriting Basic Tests with C++ with GTestWriting Basic Tests with PythonTesting Your Code with the ROS Build Farm \ No newline at end of file diff --git "a/exported_docs/ros2/Tf2\357\203\201.txt" "b/exported_docs/ros2/Tf2\357\203\201.txt" new file mode 100644 index 0000000..e7379d4 --- /dev/null +++ "b/exported_docs/ros2/Tf2\357\203\201.txt" @@ -0,0 +1,22 @@ +Title: Tf2 +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Tf2.html +Section: Installation +-------------------------------------------------------------------------------- + +Tf2Table of ContentsOverviewProperties of tf2TutorialsPaperOverviewtf2 is the transform library, which lets the user keep track of multiple coordinate frames over time. +tf2 maintains the relationship between coordinate frames in a tree structure buffered in time and lets the user transform points, vectors, etc. between any two coordinate frames at any desired point in time.Properties of tf2A robotic system typically has many 3D coordinate frames that change over time, such as a world frame, base frame, gripper frame, head frame, etc. +tf2 keeps track of all these frames over time, and allows you to ask questions like:Where was the head frame relative to the world frame 5 seconds ago?What is the pose of the object in my gripper relative to my base?What is the current pose of the base frame in the map frame?tf2 can operate in a distributed system. +This means all the information about the coordinate frames of a robot is available to all ROS 2 components on any computer in the system. +tf2 can have every component in your distributed system build its own transform information database or have a central node that gathers and stores all transform information.TutorialsWe created a set oftutorialsthat walks you through using tf2, step by step. +You can get started on theintroduction to tf2tutorial. +For a complete list of all tf2 and tf2-related tutorials check out thetutorialspage.There are essentially two main tasks that any user would use tf2 for, listening for transforms and broadcasting transforms.If you want to use tf2 to transform between coordinate frames, your nodes will need to listen for transforms. +What you will do is receive and buffer all coordinate frames that are broadcasted in the system, and query for specific transforms between frames. +Check out the “Writing a listener” tutorial(Python)(C++)to learn more.To extend the capabilities of a robot, you will need to start broadcasting transforms. +Broadcasting transforms means to send out the relative pose of coordinate frames to the rest of the system. +A system can have many broadcasters that each provide information about a different part of the robot. +Check out the “Writing a broadcaster” tutorial(Python)(C++)to learn more.In addition to that, tf2 can broadcast static transforms that do not change over time. +This mainly saves storage and lookup time, but also reduces the publishing overhead. +You should note that static transforms are published once and assumed to not change, so no history is stored. +If you want to define static transforms in your tf2 tree, take a look at the “Writing a static broadcaster”(Python)(C++)tutorial.You can also learn how to add fixed and dynamic frames to your tf2 tree in the “Adding a frame”(Python)(C++)tutorial.Once you are finished with the basic tutorials, you can move on to learn about tf2 and time. +The tf2 and time tutorial(C++)teaches the basic principles of tf2 and time. +The advanced tutorial about tf2 and time(C++)teaches the principles of time traveling with tf2.PaperThere is a paper on tf2 presented at TePRA 2013:tf: The transform library. \ No newline at end of file diff --git "a/exported_docs/ros2/The_ROS_2_Project\357\203\201.txt" "b/exported_docs/ros2/The_ROS_2_Project\357\203\201.txt" new file mode 100644 index 0000000..9d83815 --- /dev/null +++ "b/exported_docs/ros2/The_ROS_2_Project\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: The ROS 2 Project +URL: https://docs.ros.org/en/jazzy/The-ROS2-Project.html +Section: Installation +-------------------------------------------------------------------------------- + +The ROS 2 ProjectCheck out the resources below to learn more about the advancement of the ROS 2 project.ContributingFeatures StatusFeature IdeasRoadmapROSCon TalksProject GovernanceMarketingMetrics \ No newline at end of file diff --git "a/exported_docs/ros2/The_ROS_DOMAIN_ID\357\203\201.txt" "b/exported_docs/ros2/The_ROS_DOMAIN_ID\357\203\201.txt" new file mode 100644 index 0000000..e4312b2 --- /dev/null +++ "b/exported_docs/ros2/The_ROS_DOMAIN_ID\357\203\201.txt" @@ -0,0 +1,29 @@ +Title: The ROS_DOMAIN_ID +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Domain-ID.html +Section: Installation +-------------------------------------------------------------------------------- + +The ROS_DOMAIN_IDTable of ContentsOverviewChoosing a domain ID (short version)Choosing a domain ID (long version)Platform-specific constraintsParticipant constraintsDomain ID to UDP Port CalculatorOverviewAs explained elsewhere, the default middleware that ROS 2 uses for communication is DDS. +In DDS, the primary mechanism for having different logical networks share a physical network is known as the Domain ID. +ROS 2 nodes on the same domain can freely discover and send messages to each other, while ROS 2 nodes on different domains cannot. +All ROS 2 nodes use domain ID 0 by default. +To avoid interference between different groups of computers running ROS 2 on the same network, a different domain ID should be set for each group.Choosing a domain ID (short version)The text below explains the derivation of the range of domain IDs that should be used in ROS 2. +To skip that background and just choose a safe number, simply choose a domain ID between 0 and 101, inclusive.Choosing a domain ID (long version)The domain ID is used by DDS to compute the UDP ports that will be used for discovery and communication. +Seethis articlefor details on how the ports are computed. +Remembering our basic networking, the UDP port is anunsigned 16-bit integer. +Thus, the highest port number that can be allocated is 65535. +Doing some math with the formula in the article above, this means that the highest domain ID that can possibly be assigned is 232, while the lowest that can be assigned is 0.Platform-specific constraintsFor maximum compatibility, some additional platform-specific constraints should be followed when choosing a domain ID. +In particular, it is best to avoid allocating domain IDs in the operating system’sephemeral port range. +This avoids possible conflicts between the ports used by the ROS 2 nodes and other networking services on the computers.Here are some platform-specific notes about ephemeral ports.LinuxmacOSWindowsBy default, the Linux kernel uses ports 32768-60999 for ephemeral ports. +This means that domain IDs 0-101 and 215-232 can be safely used without colliding with ephemeral ports. +The ephemeral port range is configurable in Linux by setting custom values in/proc/sys/net/ipv4/ip_local_port_range. +If a custom ephemeral port range is used, the above numbers may have to be adjusted accordingly.By default, the ephemeral port range on macOS is 49152-65535. +This means that domain IDs 0-166 can be safely used without colliding with ephemeral ports. +The ephemeral port range is configurable in macOS by setting custom sysctl values fornet.inet.ip.portrange.firstandnet.inet.ip.portrange.last. +If a custom ephemeral port range is used, the above numbers may have to be adjusted accordingly.By default, the ephemeral port range on Windows is 49152-65535. +This means that domain IDs 0-166 can be safely used without colliding with ephemeral ports. +The ephemeral port range is configurable in Windows byusing netsh. +If a custom ephemeral port range is used, the above numbers may have to be adjusted accordingly.Participant constraintsFor each ROS 2 process running on a computer, one DDS “participant” is created. +Since each DDS participant takes up two ports on the computer, running more than 120 ROS 2 processes on one computer may spill over into other domain IDs or the ephemeral ports.To see why, consider the domain IDs 1 and 2.Domain ID 1 uses port 7650 and 7651 for multicast.Domain ID 2 uses port 7900 and 7901 for multicast.When creating the 1st process (zeroth participant) in domain ID 1, the ports 7660 and 7661 are used for unicast.When creating the 120th process (119th participant) in domain ID 1, the ports 7898 and 7899 are used for unicast.When creating the 121st process (120th participant) in domain ID 1, the ports 7900 and 7901 are used for unicast and overlap with domain ID 2.If it is known that the computer will only ever be on a single domain ID at a time, and the domain ID is low enough, it is safe to create more ROS 2 processes than this.When choosing a domain ID that is near the top of the range of platform-specific domain IDs, one additional constraint should be considered.For instance, assume a Linux computer with a domain ID of 101:The zero’th ROS 2 process on the computer will connect to ports 32650, 32651, 32660, and 32661.The first ROS 2 process on the computer will connect to ports 32650, 32651, 32662, and 32663.The 53rd ROS 2 process on the computer will connect to ports 32650, 32651, 32766, and 32767.The 54th ROS 2 process on the computer will connect to ports 32650, 32651, 32768, and 32769, running into the ephemeral port range.Thus the maximum number of processes that should be created when using domain ID 101 on Linux is 54. +Similarly, the maximum number of processes that should be created when using domain ID 232 on Linux is 63, as the maximum port number is 65535.The situation is similar on macOS and Windows, though the numbers are different. +On macOS and Windows, when choosing a domain ID of 166 (the top of the range), the maximum number of ROS 2 processes that can be created on a computer before running into the ephemeral port range is 120.Domain ID to UDP Port CalculatorDomain ID:Participant ID:Discovery Multicast Port:User Multicast Port:Discovery Unicast Port:User Unicast Port: \ No newline at end of file diff --git "a/exported_docs/ros2/The_Ros2Supervisor_Node\357\203\201.txt" "b/exported_docs/ros2/The_Ros2Supervisor_Node\357\203\201.txt" new file mode 100644 index 0000000..f45680a --- /dev/null +++ "b/exported_docs/ros2/The_Ros2Supervisor_Node\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: The Ros2Supervisor Node +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Simulation-Supervisor.html +Section: Installation +-------------------------------------------------------------------------------- + +The Ros2Supervisor NodeGoal:Extend the interface with a default Supervisor robot, namedRos2Supervisor.Tutorial level:AdvancedTime:10 minutesContentsBackgroundPrerequisitesTheRos2SupervisorClock topicImport a Webots nodeRemove a Webots imported nodeRecord animationsSummaryBackgroundIn this tutorial, you will learn how to enable theRos2Supervisornode which enhances the interface by creating additional services and topics to interact with the simulation. +You can, for example, record animations or spawn Webots nodes directly from the ROS 2 interface while the simulation is running. +These instructions list in details the current implemented features and how to use them.PrerequisitesBefore proceeding with this tutorial, make sure you have completed the following:Understanding of ROS 2 nodes and topics covered in the beginnerTutorials.Knowledge of Webots and ROS 2 and its interface package.Familiarity withSetting up a robot simulation (Basic).TheRos2SupervisorTheRos2Supervisoris made of two main parts:A Webots Robot node added to the simulation world. Itssupervisorfield is set to TRUE.A ROS 2 node that connects to the Webots Robot as an extern controller (in a similar way to your own robot plugin).The ROS 2 node acts as a controller that calls Supervisor API functions to control or interact with the simulation world. +User interactions with the ROS 2 node are mainly performed through services and topics.These nodes can be automatically created at the Webots launch using theros2_supervisorparameter in theWebotsLauncher.webots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]),mode=mode,ros2_supervisor=True)Thewebots._supervisorobject must also be included in theLaunchDescriptionreturned by the launch file.returnLaunchDescription([webots,webots._supervisor,# This action will kill all nodes once the Webots simulation has exitedlaunch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))])More information about launch files forwebots_ros2projects can be found inSetting up a robot simulation (Basic).Clock topicTheRos2Supervisornode is responsible to get the time of the Webots simulation and publish it to the/clocktopic. +This means that it is mandatory to spawn theRos2Supervisorif some other nodes have theiruse_sim_timeparameter set totrue. +More information about the/clocktopic can be found in theROS wiki.Import a Webots nodeTheRos2Supervisornode also allows you to spawn Webots nodes from strings through a service.The service is named/Ros2Supervisor/spawn_node_from_stringand is of typewebots_ros2_msgs/srv/SpawnNodeFromString. +TheSpawnNodeFromStringtype expects adatastring as input and returns asuccessboolean.From the given string, the Supervisor node is getting the name of the imported node and adding it to an intern list for potential later removal (seeRemove a Webots imported node).The node is imported using theimportMFNodeFromString(nodeString)API function.Here is an example to import a simple Robot namedimported_robot:ros2servicecall/Ros2Supervisor/spawn_node_from_stringwebots_ros2_msgs/srv/SpawnNodeFromString"data: Robot { name \"imported_robot\" }"NoteIf you try to import some PROTOs in the node string, their respective URLs must be declared in the .wbt world file as EXTERNPROTO or as IMPORTABLE EXTERNPROTO.Remove a Webots imported nodeOnce a node has been imported with the/Ros2Supervisor/spawn_node_from_stringservice, it can also be removed.This can be achieved by sending the name of the node to the topic named/Ros2Supervisor/remove_nodeof typestd_msgs/msg/String.If the node is indeed in the imported list, it is removed with theremove()API method.Here is an example on how to remove theimported_robotRobot:ros2topicpub--once/Ros2Supervisor/remove_nodestd_msgs/msg/String"{data: imported_robot}"Record animationsTheRos2Supervisornode also creates two additional services to record HTML5 animations.The/Ros2Supervisor/animation_start_recordingservice is of typewebots_ros2_msgs/srv/SetStringand allows to start the animation. +TheSetStringtype expects avaluestring as input and returns asuccessboolean. +The inputvaluerepresents the absolute path to the directory where the animations files should be saved.Here is an example on how to start an animation:ros2servicecall/Ros2Supervisor/animation_start_recordingwebots_ros2_msgs/srv/SetString"{value: "/index.html"}"The/Ros2Supervisor/animation_stop_recordingservice is of typewebots_ros2_msgs/srv/GetBooland allows to stop the animation.ros2servicecall/Ros2Supervisor/animation_stop_recordingwebots_ros2_msgs/srv/GetBool"{ask: True}"SummaryIn this tutorial, you learned how to enable theRos2Supervisorand how to extend the interface with the Webots simulation. +The node creates multiple services and topics to interact with and modify the simulation. + +Code Examples: + +Language: unknown +webots=WebotsLauncher(world=PathJoinSubstitution([package_dir,'worlds',world]),mode=mode,ros2_supervisor=True) + +Language: unknown +returnLaunchDescription([webots,webots._supervisor,# This action will kill all nodes once the Webots simulation has exitedlaunch.actions.RegisterEventHandler(event_handler=launch.event_handlers.OnProcessExit(target_action=webots,on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],))]) + +Language: unknown +ros2servicecall/Ros2Supervisor/spawn_node_from_stringwebots_ros2_msgs/srv/SpawnNodeFromString"data: Robot { name \"imported_robot\" }" + +Language: unknown +ros2topicpub--once/Ros2Supervisor/remove_nodestd_msgs/msg/String"{data: imported_robot}" + +Language: unknown +ros2servicecall/Ros2Supervisor/animation_start_recordingwebots_ros2_msgs/srv/SetString"{value: "/index.html"}" + +Language: unknown +ros2servicecall/Ros2Supervisor/animation_stop_recordingwebots_ros2_msgs/srv/GetBool"{ask: True}" diff --git "a/exported_docs/ros2/The_build_system\357\203\201.txt" "b/exported_docs/ros2/The_build_system\357\203\201.txt" new file mode 100644 index 0000000..d7529e9 --- /dev/null +++ "b/exported_docs/ros2/The_build_system\357\203\201.txt" @@ -0,0 +1,32 @@ +Title: The build system +URL: https://docs.ros.org/en/jazzy/Concepts/Advanced/About-Build-System.html +Section: Installation +-------------------------------------------------------------------------------- + +The build systemTable of ContentsBuild toolBuild helpersTheament_packagepackageTheament_cmakerepositoryTheament_lintrepositoryMeta-build toolThe build system is what allows developers to build their ROS 2 code as needed. +ROS 2 relies heavily on the division of code into packages, with each package containing a manifest file (package.xml). +This manifest file contains essential metadata about the package, including its dependencies on other packages. +This manifest is required for the meta-build tool to function.The ROS 2 build system consists of 3 major concepts.Build toolThis is the software that controls the compilation and testing of a single package. +In ROS 2 this is usually CMake for C++, and setuptools for Python, but other build tools are supported.Build helpersThese are helper functions that hook into the build tool to developer experience. +ROS 2 packages typically rely on theamentseries of packages for this.amentconsists of a few important repositories which are all in theGitHub organization.Theament_packagepackageLocated onGitHubatament/ament_package, this repository contains a singleament Python packagethat provides various utilities forament packages, e.g. templates for environment hooks.Allament packagesmust contain a singlepackage.xmlfile at the root of the package regardless of their underlying build system. +Thepackage.xml“manifest” file contains information that is required in order to process and operate on apackage. +Thispackageinformation includes things like thepackage’s name, which is globally unique, and the package’s dependencies. +Thepackage.xmlfile also serves as the marker file which indicates the location of thepackageon the file system.Parsing of thepackage.xmlfiles is provided bycatkin_pkg(as in ROS 1), while functionality to locatepackagesby searching the file system for thesepackage.xmlfiles is provided by build tools such ascolcon.package.xmlPackage manifest file which marks the root of apackageand contains meta information about thepackageincluding its name, version, description, maintainer, license, dependencies, and more. +The contents of the manifest are in machine readable XML format and the contents are described in theREPs127and140, with the possibility of further modifications in futureREPs.So anytime somepackageis referred to as anament package, it means that it is a single unit of software (source code, build files, tests, documentation, and other resources) which is described using apackage.xmlmanifest file.ament packageAnypackagewhich contains apackage.xmland follows the packaging guidelines ofament, regardless of the underlying build system.Since the termament packageis build system agnostic, there can be different kinds ofament packages, e.g.ament CMake package,ament Python package, etc.Here is a list of common package types that you might run into in this software stack:CMake packageAnypackagecontaining a plain CMake project and apackage.xmlmanifest file.ament CMake packageACMake packagethat also follows theamentpackaging guidelines.Python packageAnypackagecontaining asetuptoolsbased Python project and apackage.xmlmanifest file.ament Python packageAPython packagethat also follows theamentpackaging guidelines.Theament_cmakerepositoryLocated onGitHubatament/ament_cmake, this repository contains many “ament CMake” and pure CMake packages which provide the infrastructure in CMake that is required to create “ament CMake” packages. +In this context “ament CMake” packages means:amentpackages that are built using CMake. +So thepackagesin this repository provide the necessary CMake functions/macros and CMake Modules to facilitate creating more “ament CMake” (orament_cmake) packages. +Packages of this type are identified with theament_cmaketag in thetag of thepackage.xmlfile.Thepackagesin this repository are extremely modular, but there is a single “bottleneck”packagecalledament_cmake. +Anyone can depend on theament_cmakepackageto get all of the aggregate functionality of thepackagesin this repository. +Here a list of thepackagesin the repository along with a short description:ament_cmakeaggregates all otherpackagesin this repository, users need only to depend on thisament_cmake_autoprovides convenience CMake functions which automatically handle a lot of the tedious parts of writing apackage’sCMakeLists.txtfileament_cmake_coreprovides all built-in core concepts forament, e.g. environment hooks, resource indexing, symbolic linking install and othersament_cmake_gmockadds convenience functions for making gmock based unit testsament_cmake_gtestadds convenience functions for making gtest based automated testsament_cmake_noseadds convenience functions for making nosetests based python automated testsament_cmake_pythonprovides CMake functions forpackagesthat contain Python codesee theament_cmake_python user documentationament_cmake_testaggregates different kinds of tests, e.g. gtest and nosetests, under a single target usingCTestTheament_cmake_corepackagecontains a lot of the CMake infrastructure that makes it possible to cleanly pass information betweenpackagesusing conventional interfaces. +This makes thepackageshave more decoupled build interfaces with otherpackages, promoting their reuse and encouraging conventions in the build systems of differentpackages. +For instance, it provides a standard way to pass include directories, libraries, definitions, and dependencies betweenpackagesso that consumers of this information can access this information in a conventional way.Theament_cmake_corepackagealso provides features of theamentbuild system like symbolic link installation, which allows you to symbolically link files from either the source space or the build space into the install space rather than copying them. +This allows you to install once and then edit non-generated resources like Python code and configuration files without having to rerun the install step for them to take effect. +This feature essentially replaces the “devel space” fromcatkinbecause it has most of the advantages with few of the complications or drawbacks.Another feature provided byament_cmake_coreis thepackageresource indexing which is a way forpackagesto indicate that they contain a resource of some type. +The design of this feature makes it much more efficient to answer simple questions like whatpackagesare in this prefix (e.g./usr/local) because it only requires that you list the files in a single possible location under that prefix. +You can read more about this feature in thedesign docsfor the resource index.Likecatkin,ament_cmake_corealso provides environment setup files andpackagespecific environment hooks. +The environment setup files, often named something likesetup.bash, are a place forpackagedevelopers to define changes to the environment that are needed to utilize theirpackage. +The developers are able to do this using an “environment hook” which is basically an arbitrary bit of shell code that can set or modify environment variables, define shell functions, setup auto-completion rules, etc… +This feature is how, for example, ROS 1 set theROS_DISTROenvironment variable withoutcatkinknowing anything about the ROS distribution.Theament_lintrepositoryLocated onGitHubatament/ament_lint, this repository provides severalpackageswhich provide linting and testing services in a convenient and consistent manner. +Currently there arepackagesto support C++ style linting usinguncrustify, static C++ code checks usingcppcheck, checking for copyright in source code, Python style linting usingpep8, and other things. +The list of helper packages will likely grow in the future.Meta-build toolThis is a piece of software that knows how to topologically order a group of packages, and build or test them in the correct dependency order. +This software will call into the Build Tool to do the actual work of compiling, testing, and installing the package.In ROS 2, the tool namedcolconis used for this. \ No newline at end of file diff --git "a/exported_docs/ros2/Topic_statistics\357\203\201.txt" "b/exported_docs/ros2/Topic_statistics\357\203\201.txt" new file mode 100644 index 0000000..e7cb56d --- /dev/null +++ "b/exported_docs/ros2/Topic_statistics\357\203\201.txt" @@ -0,0 +1,19 @@ +Title: Topic statistics +URL: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Topic-Statistics.html +Section: Installation +-------------------------------------------------------------------------------- + +Topic statisticsTable of ContentsOverviewHow statistics are calculatedTypes of statistics calculatedBehaviorComparison to ROS 1SupportOverviewROS 2 provides integrated measurement of statistics for messages received by any subscription. +Allowing a user to collect subscription statistics enables them to characterize the performance of their system or aid in diagnosis of any present issues.The measurements provided are the received message age and received message period. +For each measurement the statistics provided are the average, maximum, minimum, standard deviation, and sample count. +These statistics are calculated in a moving window.How statistics are calculatedEach statistic set is calculated in constant time and constant memory by using the utilities implemented in thelibstatistics_collectorpackage. +When a new message is received by a subscription, this is a new sample for calculation in the current measurement window. +The average calculated is simply amoving average. +The maximum, minimum, and sample count are updated upon receipt of each new sample, whereas the standard deviation is calculated usingWelford’s online algorithm.Types of statistics calculatedReceived message periodUnits: millisecondsUses the system clock to measure the period between received messagesReceived message ageUnits: millisecondsRequires a message to have a timestamp populated in the header field in order to calculate the age of the message as sent from a publisherBehaviorBy default, Topic Statistics measurements are not enabled. +After enabling this feature for a specific node via the subscription configuration options, both received message age and received message period measurements are enabled for that specific subscription.The data is published as astatistics_msg/msg/MetricsMessageat a configurable period (default 1 second) to a configurable topic (default/statistics). +Note that the publishing period also serves as the sample collection window period.Since received message period requires a message timestamp in a header field, empty data is published. +That is, all statistics values are NaN if no timestamp is found. +Publishing NaN values instead of not publishing at all avoids the absence of a signal problem and is meant to explicitly show that a measurement could not be made.The first sample of each window for the received message period statistic does not yield a measurement. +This is because calculating this statistic requires knowing the time the previous message arrived, so subsequent samples in the window yield measurements.Comparison to ROS 1Similar to ROS 1Topic Statistics, both message age and message period are calculated, albeit from the subscription side. +Other ROS 1 metrics, e.g., the number of dropped messages or traffic volume, are currently not provided.SupportThis feature is currently supported in ROS 2 Foxy for C++ only (rclcpp). +Future work and improvements, such as Python support, can be foundhere. \ No newline at end of file diff --git "a/exported_docs/ros2/Topics_vs_Services_vs_Actions\357\203\201.txt" "b/exported_docs/ros2/Topics_vs_Services_vs_Actions\357\203\201.txt" new file mode 100644 index 0000000..047508f --- /dev/null +++ "b/exported_docs/ros2/Topics_vs_Services_vs_Actions\357\203\201.txt" @@ -0,0 +1,8 @@ +Title: Topics vs Services vs Actions +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Topics-Services-Actions.html +Section: Installation +-------------------------------------------------------------------------------- + +Topics vs Services vs ActionsContentsTopicsServicesActionsWhen designing a system there are three primary styles of interfaces. +The specifications for the content is in theInterfaces Overview. +This is written to provide the reader with guidelines about when to use each type of interface.TopicsShould be used for continuous data streams (sensor data, robot state, …).Are for continuous data flow. Data might be published and subscribed at any time independent of any senders/receivers. Many to many connection. Callbacks receive data once it is available. The publisher decides when data is sent.ServicesShould be used for remote procedure calls that terminate quickly, e.g. for querying the state of a node or doing a quick calculation such as IK. They should never be used for longer running processes, in particular processes that might be required to preempt if exceptional situations occur and they should never change or depend on state to avoid unwanted side effects for other nodes.Simple blocking call. Mostly used for comparably fast tasks as requesting specific data. Semantically for processing requests.ActionsShould be used for any discrete behavior that moves a robot or that runs for a longer time but provides feedback during execution.The most important property of actions is that they can be preempted and preemption should always be implemented cleanly by action servers.Actions can keep state for the lifetime of a goal, i.e. if executing two action goals in parallel on the same server, for each client a separate state instance can be kept since the goal is uniquely identified by its id.Slow perception routines which take several seconds to terminate or initiating a lower-level control mode are good use cases for actions.More complex non-blocking background processing. Used for longer tasks like execution of robot actions. Semantically for real-world actions. \ No newline at end of file diff --git "a/exported_docs/ros2/Topics\357\203\201.txt" "b/exported_docs/ros2/Topics\357\203\201.txt" new file mode 100644 index 0000000..40ba347 --- /dev/null +++ "b/exported_docs/ros2/Topics\357\203\201.txt" @@ -0,0 +1,27 @@ +Title: Topics +URL: https://docs.ros.org/en/jazzy/Concepts/Basic/About-Topics.html +Section: Installation +-------------------------------------------------------------------------------- + +TopicsTable of ContentsPublish/SubscribeAnonymousStrongly-typedTopics are one of the three primary styles of interfaces provided by ROS 2. +Topics should be used for continuous data streams, like sensor data, robot state, etc.As stated earlier, ROS 2 is a strongly-typed, anonymous publish/subscribe system. +Let’s break down that sentence and explain it a bit more.Publish/SubscribeA publish/subscribe system is one in which there are producers of data (publishers) and consumers of data (subscribers). +The publishers and subscribers know how to contact each other through the concept of a “topic”, which is a common name so that the entites can find each other. +For instance, when you create a publisher, you must also give it a string that is the name of the topic; the same goes for the subscriber. +Any publishers and subscribers that are on the same topic name can directly communicate with each other. +There may be zero or more publishers and zero or more subscribers on any particular topic. +When data is published to the topic by any of the publishers, all subscribers in the system will receive the data. +This system is also known as a “bus”, since it somewhat resembles a device bus from electrical engineering. +This concept of a bus is part of what makes ROS 2 a powerful and flexible system. +Publishers and subscribers can come and go as needed, meaning that debugging and introspection are natural extensions to the system. +For instance, if you want to record data, you can use theros2bagrecordcommand. +Under the hood,ros2bagrecordcreates a new subscriber to whatever topic you tell it, without interrupting the flow of data to the other parts of the system.AnonymousAnother fact mentioned in the introduction is that ROS 2 is “anonymous”. +This means that when a subscriber gets a piece of data, it doesn’t generally know or care which publisher originally sent it (though it can find out if it wants). +The benefit to this architecture is that publishers and subscribers can be swapped out at will without affecting the rest of the system.Strongly-typedFinally, the introduction also mentioned that the publish/subscribe system is “strongly-typed”. +That has two meanings in this context:The types of each field in a ROS message are typed, and that type is enforced at various levels. +For instance, if the ROS message contains:uint32field1stringfield2Then the code will ensure thatfield1is always an unsigned integer and thatfield2is always a string.The semantics of each field are well-defined. There is no automated mechanism to ensure this, but all of the core ROS types have strong semantics associated with them. For instance, the IMU message contains a 3-dimensional vector for the measured angular velocity, and each of the dimensions is specified to be in radians/second. Other interpretations should not be placed into the message. + +Code Examples: + +Language: unknown +uint32field1stringfield2 diff --git "a/exported_docs/ros2/Traveling_in_time_(C++)\357\203\201.txt" "b/exported_docs/ros2/Traveling_in_time_(C++)\357\203\201.txt" new file mode 100644 index 0000000..1134714 --- /dev/null +++ "b/exported_docs/ros2/Traveling_in_time_(C++)\357\203\201.txt" @@ -0,0 +1,33 @@ +Title: Traveling in time (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Time-Travel-With-Tf2-Cpp.html +Section: Installation +-------------------------------------------------------------------------------- + +Traveling in time (C++)Goal:Learn about advanced time travel features of tf2.Tutorial level:IntermediateTime:10 minutesContentsBackgroundTime travelAdvanced API for lookupTransform()Checking the resultsSummaryBackgroundIn the previous tutorial, we discussed thebasics of tf2 and time. +This tutorial will take us one step further and expose a powerful tf2 trick: the time travel. +In short, one of the key features of tf2 library is that it is able to transform data in time as well as in space.This tf2 time travel feature can be useful for various tasks, like monitoring the pose of the robot for a long period of time or building a follower robot that will follow the “steps” of the leader. +We will use that time travel feature to look up transforms back in time and programturtle2to follow 5 seconds behindcarrot1.Time travelFirst, let’s go back to where we ended in the previous tutorialUsing time. +Go to yourlearning_tf2_cpppackage.Now, instead of making the second turtle go to where the carrot is now, we will make the second turtle go to where the first carrot was 5 seconds ago. +Edit thelookupTransform()call inturtle_tf2_listener.cppfile torclcpp::Timewhen=this->get_clock()->now()-rclcpp::Duration(5,0);try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,when,50ms);}catch(consttf2::TransformException&ex){Now if you run this, during the first 5 seconds, the second turtle would not know where to go because we do not yet have a 5-second history of poses of the carrot. +But what happens after these 5 seconds? Build the package then let’s just give it a try:ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo_launch.pyYou should now notice that your turtle is driving around uncontrollably like in this screenshot. Let’s try to understand reason behind that behavior.In our code we asked tf2 the following question: “What was the pose ofcarrot15 seconds ago, relative toturtle25 seconds ago?”. This means we are controlling the second turtle based on where it was 5 seconds ago as well as where the first carrot was 5 seconds ago.However, what we really want to ask is: “What was the pose ofcarrot15 seconds ago, relative to the current position of theturtle2?”.Advanced API for lookupTransform()To ask the tf2 that particular question, we will use an advanced API that gives us the power to say explicitly when to acquire the specified transformations. +This is done by calling thelookupTransform()method with additional parameters. +Your code now would look like this:rclcpp::Timenow=this->get_clock()->now();rclcpp::Timewhen=now-rclcpp::Duration(5,0);try{t=tf_buffer_->lookupTransform(toFrameRel,now,fromFrameRel,when,"world",50ms);}catch(consttf2::TransformException&ex){The advanced API forlookupTransform()takes six arguments:Target frameThe time to transform toSource frameThe time at which source frame will be evaluatedFrame that does not change over time, in this case theworldframeTime to wait for the target frame to become availableTo sum up, tf2 does the following in the background. +In the past, it computes the transform from thecarrot1to theworld. +In theworldframe, tf2 time travels from the past to now. +And at the current time, tf2 computes the transform from theworldto theturtle2.Checking the resultsBuild the package then let’s run the simulation again, this time with the advanced time-travel API:ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo_launch.pyAnd yes, the second turtle is directed to where the first carrot was 5 seconds ago!SummaryIn this tutorial, you have seen one of the advanced features of tf2. +You learned that tf2 can transform data in time and learned how to do that with turtlesim example. +tf2 allowed you to go back in time and make frame transformations between old and current poses of turtles by using the advancedlookupTransform()API. + +Code Examples: + +Language: unknown +rclcpp::Timewhen=this->get_clock()->now()-rclcpp::Duration(5,0);try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,when,50ms);}catch(consttf2::TransformException&ex){ + +Language: unknown +ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo_launch.py + +Language: unknown +rclcpp::Timenow=this->get_clock()->now();rclcpp::Timewhen=now-rclcpp::Duration(5,0);try{t=tf_buffer_->lookupTransform(toFrameRel,now,fromFrameRel,when,"world",50ms);}catch(consttf2::TransformException&ex){ + +Language: unknown +ros2 launch learning_tf2_cpp turtle_tf2_fixed_frame_demo_launch.py diff --git a/exported_docs/ros2/Tutorials.txt b/exported_docs/ros2/Tutorials.txt new file mode 100644 index 0000000..80138ae --- /dev/null +++ b/exported_docs/ros2/Tutorials.txt @@ -0,0 +1,5 @@ +Title: Tutorials +URL: https://docs.ros.org/en/jazzy/Tutorials.html +Section: Tutorials +-------------------------------------------------------------------------------- + diff --git "a/exported_docs/ros2/URDF\357\203\201.txt" "b/exported_docs/ros2/URDF\357\203\201.txt" new file mode 100644 index 0000000..e640c6b --- /dev/null +++ "b/exported_docs/ros2/URDF\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: URDF +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/URDF/URDF-Main.html +Section: Installation +-------------------------------------------------------------------------------- + +URDFURDF (Unified Robot Description Format) is a file format for specifying the geometry and organization of robots in ROS.Building a visual robot model from scratchBuilding a movable robot modelAdding physical and collision propertiesUsing Xacro to clean up your codeUsing URDF withrobot_state_publisherGenerating an URDF File \ No newline at end of file diff --git "a/exported_docs/ros2/Ubuntu_(deb_packages)\357\203\201.txt" "b/exported_docs/ros2/Ubuntu_(deb_packages)\357\203\201.txt" new file mode 100644 index 0000000..0df5bbc --- /dev/null +++ "b/exported_docs/ros2/Ubuntu_(deb_packages)\357\203\201.txt" @@ -0,0 +1,79 @@ +Title: Ubuntu (deb packages) +URL: https://docs.ros.org/en/jazzy/Installation/Ubuntu-Install-Debs.html +Section: Installation +-------------------------------------------------------------------------------- + +Ubuntu (deb packages)Table of ContentsResourcesSystem setupSet localeEnable required repositoriesInstall development tools (optional)Install ROS 2Install additional RMW implementations (optional)Setup environmentTry some examplesNext stepsTroubleshootUninstallDeb packages for ROS 2 Jazzy Jalisco are currently available for Ubuntu Noble (24.04). +The target platforms are defined inREP 2000.ResourcesStatus Page:ROS 2 Jazzy (Ubuntu Noble 24.04):amd64,arm64Jenkins InstanceRepositoriesSystem setupSet localeMake sure you have a locale which supportsUTF-8. +If you are in a minimal environment (such as a docker container), the locale may be something minimal likePOSIX. +We test with the following settings. However, it should be fine if you’re using a different UTF-8 supported locale.locale# check for UTF-8sudoaptupdate&&sudoaptinstalllocales +sudolocale-genen_USen_US.UTF-8 +sudoupdate-localeLC_ALL=en_US.UTF-8LANG=en_US.UTF-8exportLANG=en_US.UTF-8 + +locale# verify settingsEnable required repositoriesYou will need to add the ROS 2 apt repository to your system.First ensure that theUbuntu Universe repositoryis enabled.sudoaptinstallsoftware-properties-common +sudoadd-apt-repositoryuniverseNow add the ROS 2 GPG key with apt.sudoaptupdate&&sudoaptinstallcurl-y +sudocurl-sSLhttps://raw.githubusercontent.com/ros/rosdistro/master/ros.key-o/usr/share/keyrings/ros-archive-keyring.gpgThen add the repository to your sources list.echo"deb [arch=$(dpkg--print-architecture)signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu$(./etc/os-release&&echo$UBUNTU_CODENAME)main"|sudotee/etc/apt/sources.list.d/ros2.list>/dev/nullInstall development tools (optional)If you are going to build ROS packages or otherwise do development, you can also install the development tools:sudoaptupdate&&sudoaptinstallros-dev-toolsInstall ROS 2Update your apt repository caches after setting up the repositories.sudoaptupdateROS 2 packages are built on frequently updated Ubuntu systems. +It is always recommended that you ensure your system is up to date before installing new packages.sudoaptupgradeDesktop Install (Recommended): ROS, RViz, demos, tutorials.sudoaptinstallros-jazzy-desktopROS-Base Install (Bare Bones): Communication libraries, message packages, command line tools. +No GUI tools.sudoaptinstallros-jazzy-ros-baseInstall additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at runtime. +See theguideon how to work with multiple RMWs.Setup environmentSet up your environment by sourcing the following file.# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zshsource/opt/ros/jazzy/setup.bashTry some examplesIf you installedros-jazzy-desktopabove you can try some examples.In one terminal, source the setup file and then run a C++talker:source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_cpptalkerIn another terminal source the setup file and then run a Pythonlistener:source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you need to uninstall ROS 2 or switch to a source-based install once you +have already installed from binaries, run the following command:sudoaptremove~nros-jazzy-*&&sudoaptautoremoveYou may also want to remove the repository:sudorm/etc/apt/sources.list.d/ros2.list +sudoaptupdate +sudoaptautoremove# Consider upgrading for packages previously shadowed.sudoaptupgrade + +Code Examples: + +Language: unknown +locale# check for UTF-8sudoaptupdate&&sudoaptinstalllocales +sudolocale-genen_USen_US.UTF-8 +sudoupdate-localeLC_ALL=en_US.UTF-8LANG=en_US.UTF-8exportLANG=en_US.UTF-8 + +locale# verify settings + +Language: unknown +sudoaptinstallsoftware-properties-common +sudoadd-apt-repositoryuniverse + +Language: unknown +sudoaptupdate&&sudoaptinstallcurl-y +sudocurl-sSLhttps://raw.githubusercontent.com/ros/rosdistro/master/ros.key-o/usr/share/keyrings/ros-archive-keyring.gpg + +Language: unknown +echo"deb [arch=$(dpkg--print-architecture)signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu$(./etc/os-release&&echo$UBUNTU_CODENAME)main"|sudotee/etc/apt/sources.list.d/ros2.list>/dev/null + +Language: unknown +sudoaptupdate&&sudoaptinstallros-dev-tools + +Language: unknown +sudoaptupdate + +Language: unknown +sudoaptupgrade + +Language: unknown +sudoaptinstallros-jazzy-desktop + +Language: unknown +sudoaptinstallros-jazzy-ros-base + +Language: unknown +# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zshsource/opt/ros/jazzy/setup.bash + +Language: unknown +source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_cpptalker + +Language: unknown +source/opt/ros/jazzy/setup.bash +ros2rundemo_nodes_pylistener + +Language: unknown +sudoaptremove~nros-jazzy-*&&sudoaptautoremove + +Language: unknown +sudorm/etc/apt/sources.list.d/ros2.list +sudoaptupdate +sudoaptautoremove# Consider upgrading for packages previously shadowed.sudoaptupgrade diff --git "a/exported_docs/ros2/Ubuntu_(source)\357\203\201.txt" "b/exported_docs/ros2/Ubuntu_(source)\357\203\201.txt" new file mode 100644 index 0000000..c9237a1 --- /dev/null +++ "b/exported_docs/ros2/Ubuntu_(source)\357\203\201.txt" @@ -0,0 +1,91 @@ +Title: Ubuntu (source) +URL: https://docs.ros.org/en/jazzy/Installation/Alternatives/Ubuntu-Development-Setup.html +Section: Installation +-------------------------------------------------------------------------------- + +Ubuntu (source)Table of ContentsSystem requirementsSystem setupSet localeEnable required repositoriesInstall development toolsBuild ROS 2Get ROS 2 codeInstall dependencies using rosdepInstall additional RMW implementations (optional)Build the code in the workspaceSetup environmentTry some examplesNext stepsAlternate compilersClangStay up to dateTroubleshootUninstallSystem requirementsThe current Debian-based target platforms for Jazzy Jalisco are:Tier 1: Ubuntu Linux - Noble (24.04) 64-bitTier 3: Ubuntu Linux - Jammy (22.04) 64-bitTier 3: Debian Linux - Bookworm (12) 64-bitAs defined inREP 2000.System setupSet localeMake sure you have a locale which supportsUTF-8. +If you are in a minimal environment (such as a docker container), the locale may be something minimal likePOSIX. +We test with the following settings. However, it should be fine if you’re using a different UTF-8 supported locale.locale# check for UTF-8sudoaptupdate&&sudoaptinstalllocales +sudolocale-genen_USen_US.UTF-8 +sudoupdate-localeLC_ALL=en_US.UTF-8LANG=en_US.UTF-8exportLANG=en_US.UTF-8 + +locale# verify settingsEnable required repositoriesYou will need to add the ROS 2 apt repository to your system.First ensure that theUbuntu Universe repositoryis enabled.sudoaptinstallsoftware-properties-common +sudoadd-apt-repositoryuniverseNow add the ROS 2 GPG key with apt.sudoaptupdate&&sudoaptinstallcurl-y +sudocurl-sSLhttps://raw.githubusercontent.com/ros/rosdistro/master/ros.key-o/usr/share/keyrings/ros-archive-keyring.gpgThen add the repository to your sources list.echo"deb [arch=$(dpkg--print-architecture)signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu$(./etc/os-release&&echo$UBUNTU_CODENAME)main"|sudotee/etc/apt/sources.list.d/ros2.list>/dev/nullInstall development toolssudoaptupdate&&sudoaptinstall-y\python3-flake8-blind-except\python3-flake8-class-newline\python3-flake8-deprecated\python3-mypy\python3-pip\python3-pytest\python3-pytest-cov\python3-pytest-mock\python3-pytest-repeat\python3-pytest-rerunfailures\python3-pytest-runner\python3-pytest-timeout\ros-dev-toolsBuild ROS 2Get ROS 2 codeCreate a workspace and clone all repos:mkdir-p~/ros2_jazzy/srccd~/ros2_jazzy +vcsimport--inputhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repossrcInstall dependencies using rosdepROS 2 packages are built on frequently updated Ubuntu systems. +It is always recommended that you ensure your system is up to date before installing new packages.sudoaptupgradesudorosdepinit +rosdepupdate +rosdepinstall--from-pathssrc--ignore-src-y--skip-keys"fastcdr rti-connext-dds-6.0.1 urdfdom_headers"Note: If you’re using a distribution that is based on Ubuntu (like Linux Mint) but does not identify itself as such, you’ll get an error message likeUnsupportedOS[mint]. In this case append--os=ubuntu:nobleto the above command.Install additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at build or runtime. +See theguideon how to work with multiple RMWs.Build the code in the workspaceIf you have already installed ROS 2 another way (either via debs or the binary distribution), make sure that you run the below commands in a fresh environment that does not have those other installations sourced. +Also ensure that you do not havesource/opt/ros/${ROS_DISTRO}/setup.bashin your.bashrc. +You can make sure that ROS 2 is not sourced with the commandprintenv|grep-iROS. +The output should be empty.More info on working with a ROS workspace can be found inthis tutorial.cd~/ros2_jazzy/ +colconbuild--symlink-installNoteIf you are having trouble compiling all examples and this is preventing you from completing a successful build, you can use the--packages-skipcolcon flag to ignore the package that is causing problems. +For instance, if you don’t want to install the large OpenCV library, you could skip building the packages that depend on it using the command:colconbuild--symlink-install--packages-skipimage_toolsintra_process_demoSetup environmentSet up your environment by sourcing the following file.# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zsh.~/ros2_jazzy/install/local_setup.bashTry some examplesIn one terminal, source the setup file and then run a C++talker:.~/ros2_jazzy/install/local_setup.bash +ros2rundemo_nodes_cpptalkerIn another terminal source the setup file and then run a Pythonlistener:.~/ros2_jazzy/install/local_setup.bash +ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.Alternate compilersUsing a different compiler besides gcc to compile ROS 2 is easy. +If you set the environment variablesCCandCXXto executables for a working C and C++ compiler, respectively, and retrigger CMake configuration (by using--cmake-force-configureor by deleting the packages you want to be affected), CMake will reconfigure and use the different compiler.ClangTo configure CMake to detect and use Clang:sudoaptinstallclangexportCC=clangexportCXX=clang++ +colconbuild--cmake-force-configureStay up to dateSeeMaintain source checkoutto periodically refresh your source installation.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you installed your workspace with colcon as instructed above, “uninstalling” could be just a matter of opening a new terminal and not sourcing the workspace’ssetupfile. +This way, your environment will behave as though there is no Jazzy install on your system.If you’re also trying to free up space, you can delete the entire workspace directory with:rm-rf~/ros2_jazzy + +Code Examples: + +Language: unknown +locale# check for UTF-8sudoaptupdate&&sudoaptinstalllocales +sudolocale-genen_USen_US.UTF-8 +sudoupdate-localeLC_ALL=en_US.UTF-8LANG=en_US.UTF-8exportLANG=en_US.UTF-8 + +locale# verify settings + +Language: unknown +sudoaptinstallsoftware-properties-common +sudoadd-apt-repositoryuniverse + +Language: unknown +sudoaptupdate&&sudoaptinstallcurl-y +sudocurl-sSLhttps://raw.githubusercontent.com/ros/rosdistro/master/ros.key-o/usr/share/keyrings/ros-archive-keyring.gpg + +Language: unknown +echo"deb [arch=$(dpkg--print-architecture)signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu$(./etc/os-release&&echo$UBUNTU_CODENAME)main"|sudotee/etc/apt/sources.list.d/ros2.list>/dev/null + +Language: unknown +sudoaptupdate&&sudoaptinstall-y\python3-flake8-blind-except\python3-flake8-class-newline\python3-flake8-deprecated\python3-mypy\python3-pip\python3-pytest\python3-pytest-cov\python3-pytest-mock\python3-pytest-repeat\python3-pytest-rerunfailures\python3-pytest-runner\python3-pytest-timeout\ros-dev-tools + +Language: unknown +mkdir-p~/ros2_jazzy/srccd~/ros2_jazzy +vcsimport--inputhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repossrc + +Language: unknown +sudoaptupgrade + +Language: unknown +sudorosdepinit +rosdepupdate +rosdepinstall--from-pathssrc--ignore-src-y--skip-keys"fastcdr rti-connext-dds-6.0.1 urdfdom_headers" + +Language: unknown +cd~/ros2_jazzy/ +colconbuild--symlink-install + +Language: unknown +colconbuild--symlink-install--packages-skipimage_toolsintra_process_demo + +Language: unknown +# Replace ".bash" with your shell if you're not using bash# Possible values are: setup.bash, setup.sh, setup.zsh.~/ros2_jazzy/install/local_setup.bash + +Language: unknown +.~/ros2_jazzy/install/local_setup.bash +ros2rundemo_nodes_cpptalker + +Language: unknown +.~/ros2_jazzy/install/local_setup.bash +ros2rundemo_nodes_pylistener + +Language: unknown +sudoaptinstallclangexportCC=clangexportCXX=clang++ +colconbuild--cmake-force-configure + +Language: unknown +rm-rf~/ros2_jazzy diff --git "a/exported_docs/ros2/Understanding_actions\357\203\201.txt" "b/exported_docs/ros2/Understanding_actions\357\203\201.txt" new file mode 100644 index 0000000..99b3096 --- /dev/null +++ "b/exported_docs/ros2/Understanding_actions\357\203\201.txt" @@ -0,0 +1,113 @@ +Title: Understanding actions +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Actions/Understanding-ROS2-Actions.html +Section: Installation +-------------------------------------------------------------------------------- + +Understanding actionsGoal:Introspect actions in ROS 2.Tutorial level:BeginnerTime:15 minutesContentsBackgroundPrerequisitesTasks1 Setup2 Use actions3 ros2 node info4 ros2 action list5 ros2 action type6 ros2 action info7 ros2 interface show8 ros2 action send_goalSummaryNext stepsRelated contentBackgroundActions are one of the communication types in ROS 2 and are intended for long running tasks. +They consist of three parts: a goal, feedback, and a result.Actions are built on topics and services. +Their functionality is similar to services, except actions can be canceled. +They also provide steady feedback, as opposed to services which return a single response.Actions use a client-server model, similar to the publisher-subscriber model (described in thetopics tutorial). +An “action client” node sends a goal to an “action server” node that acknowledges the goal and returns a stream of feedback and a result.PrerequisitesThis tutorial builds off concepts, likenodesandtopics, covered in previous tutorials.This tutorial uses theturtlesim package.As always, don’t forget to source ROS 2 inevery new terminal you open.Tasks1 SetupStart up the two turtlesim nodes,/turtlesimand/teleop_turtle.Open a new terminal and run:ros2 run turtlesim turtlesim_nodeOpen another terminal and run:ros2 run turtlesim turtle_teleop_key2 Use actionsWhen you launch the/teleop_turtlenode, you will see the following message in your terminal:Use arrow keys to move the turtle.Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.Let’s focus on the second line, which corresponds to an action. +(The first instruction corresponds to the “cmd_vel” topic, discussed previously in thetopics tutorial.)Notice that the letter keysG|B|V|C|D|E|R|Tform a “box” around theFkey on a US QWERTY keyboard (if you are not using a QWERTY keyboard, seethis linkto follow along). +Each key’s position aroundFcorresponds to that orientation in turtlesim. +For example, theEwill rotate the turtle’s orientation to the upper left corner.Pay attention to the terminal where the/turtlesimnode is running. +Each time you press one of these keys, you are sending a goal to an action server that is part of the/turtlesimnode. +The goal is to rotate the turtle to face a particular direction. +A message relaying the result of the goal should display once the turtle completes its rotation:[INFO] [turtlesim]: Rotation goal completed successfullyTheFkey will cancel a goal mid-execution.Try pressing theCkey, and then pressing theFkey before the turtle can complete its rotation. +In the terminal where the/turtlesimnode is running, you will see the message:[INFO] [turtlesim]: Rotation goal canceledNot only can the client-side (your input in the teleop) stop a goal, but the server-side (the/turtlesimnode) can as well. +When the server-side chooses to stop processing a goal, it is said to “abort” the goal.Try hitting theDkey, then theGkey before the first rotation can complete. +In the terminal where the/turtlesimnode is running, you will see the message:[WARN] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goalThis action server chose to abort the first goal because it got a new one. +It could have chosen something else, like reject the new goal or execute the second goal after the first one finished. +Don’t assume every action server will choose to abort the current goal when it gets a new one.3 ros2 node infoTo see the list of actions a node provides,/turtlesimin this case, open a new terminal and run the command:ros2 node info /turtlesimWhich will return a list of/turtlesim’s subscribers, publishers, services, action servers and action clients:/turtlesimSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEvent/turtle1/cmd_vel: geometry_msgs/msg/TwistPublishers:/parameter_events: rcl_interfaces/msg/ParameterEvent/rosout: rcl_interfaces/msg/Log/turtle1/color_sensor: turtlesim/msg/Color/turtle1/pose: turtlesim/msg/PoseService Servers:/clear: std_srvs/srv/Empty/kill: turtlesim/srv/Kill/reset: std_srvs/srv/Empty/spawn: turtlesim/srv/Spawn/turtle1/set_pen: turtlesim/srv/SetPen/turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute/turtle1/teleport_relative: turtlesim/srv/TeleportRelative/turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters/turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes/turtlesim/get_parameters: rcl_interfaces/srv/GetParameters/turtlesim/list_parameters: rcl_interfaces/srv/ListParameters/turtlesim/set_parameters: rcl_interfaces/srv/SetParameters/turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomicallyService Clients:Action Servers:/turtle1/rotate_absolute: turtlesim/action/RotateAbsoluteAction Clients:Notice that the/turtle1/rotate_absoluteaction for/turtlesimis underActionServers. +This means/turtlesimresponds to and provides feedback for the/turtle1/rotate_absoluteaction.The/teleop_turtlenode has the name/turtle1/rotate_absoluteunderActionClientsmeaning that it sends goals for that action name. +To see that, run:ros2 node info /teleop_turtleWhich will return:/teleop_turtleSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEventPublishers:/parameter_events: rcl_interfaces/msg/ParameterEvent/rosout: rcl_interfaces/msg/Log/turtle1/cmd_vel: geometry_msgs/msg/TwistService Servers:/teleop_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters/teleop_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes/teleop_turtle/get_parameters: rcl_interfaces/srv/GetParameters/teleop_turtle/list_parameters: rcl_interfaces/srv/ListParameters/teleop_turtle/set_parameters: rcl_interfaces/srv/SetParameters/teleop_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomicallyService Clients:Action Servers:Action Clients:/turtle1/rotate_absolute: turtlesim/action/RotateAbsolute4 ros2 action listTo identify all the actions in the ROS graph, run the command:ros2 action listWhich will return:/turtle1/rotate_absoluteThis is the only action in the ROS graph right now. +It controls the turtle’s rotation, as you saw earlier. +You also already know that there is one action client (part of/teleop_turtle) and one action server (part of/turtlesim) for this action from using theros2nodeinfocommand.4.1 ros2 action list -tActions have types, similar to topics and services. +To find/turtle1/rotate_absolute’s type, run the command:ros2 action list -tWhich will return:/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]In brackets to the right of each action name (in this case only/turtle1/rotate_absolute) is the action type,turtlesim/action/RotateAbsolute. +You will need this when you want to execute an action from the command line or from code.5 ros2 action typeIf you want to check the action type for the action, run the command:ros2 action type /turtle1/rotate_absoluteWhich will return:turtlesim/action/RotateAbsolute6 ros2 action infoYou can further introspect the/turtle1/rotate_absoluteaction with the command:ros2 action info /turtle1/rotate_absoluteWhich will returnAction: /turtle1/rotate_absoluteAction clients: 1/teleop_turtleAction servers: 1/turtlesimThis tells us what we learned earlier from runningros2nodeinfoon each node: +The/teleop_turtlenode has an action client and the/turtlesimnode has an action server for the/turtle1/rotate_absoluteaction.7 ros2 interface showOne more piece of information you will need before sending or executing an action goal yourself is the structure of the action type.Recall that you identified/turtle1/rotate_absolute’s type when running the commandros2actionlist-t. +Enter the following command with the action type in your terminal:ros2 interface show turtlesim/action/RotateAbsoluteWhich will return:#Thedesiredheadinginradiansfloat32 theta---#Theangulardisplacementinradianstothestartingpositionfloat32 delta---#Theremainingrotationinradiansfloat32 remainingThe section of this message above the first---is the structure (data type and name) of the goal request. +The next section is the structure of the result. +The last section is the structure of the feedback.8 ros2 action send_goalNow let’s send an action goal from the command line with the following syntax:ros2 action send_goal need to be in YAML format.Keep an eye on the turtlesim window, and enter the following command into your terminal:ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"You should see the turtle rotating, as well as the following message in your terminal:Waiting for an action server to become available...Sending goal:theta: 1.57Goal accepted with ID: f8db8f44410849eaa93d3feb747dd444Result:delta: -1.568000316619873Goal finished with status: SUCCEEDEDAll goals have a unique ID, shown in the return message. +You can also see the result, a field with the namedelta, which is the displacement to the starting position.To see the feedback of this goal, add--feedbackto theros2actionsend_goalcommand:ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedbackYour terminal will return the message:Sending goal:theta: -1.57Goal accepted with ID: e6092c831f994afda92f0086f220da27Feedback:remaining: -3.1268222332000732Feedback:remaining: -3.1108222007751465…Result:delta: 3.1200008392333984Goal finished with status: SUCCEEDEDYou will continue to receive feedback, the remaining radians, until the goal is complete.SummaryActions are like services that allow you to execute long running tasks, provide regular feedback, and are cancelable.A robot system would likely use actions for navigation. +An action goal could tell a robot to travel to a position. +While the robot navigates to the position, it can send updates along the way (i.e. feedback), and then a final result message once it’s reached its destination.Turtlesim has an action server that action clients can send goals to for rotating turtles. +In this tutorial, you introspected that action,/turtle1/rotate_absolute, to get a better idea of what actions are and how they work.Next stepsNow you’ve covered all of the core ROS 2 concepts. +The last few tutorials in this set will introduce you to some tools and techniques that will make using ROS 2 easier, starting withUsing rqt_console to view logs.Related contentYou can read more about the design decisions behind actions in ROS 2here. + +Code Examples: + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +Use arrow keys to move the turtle.Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation. + +Language: unknown +[INFO] [turtlesim]: Rotation goal completed successfully + +Language: unknown +[INFO] [turtlesim]: Rotation goal canceled + +Language: unknown +[WARN] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goal + +Language: unknown +ros2 node info /turtlesim + +Language: unknown +/turtlesimSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEvent/turtle1/cmd_vel: geometry_msgs/msg/TwistPublishers:/parameter_events: rcl_interfaces/msg/ParameterEvent/rosout: rcl_interfaces/msg/Log/turtle1/color_sensor: turtlesim/msg/Color/turtle1/pose: turtlesim/msg/PoseService Servers:/clear: std_srvs/srv/Empty/kill: turtlesim/srv/Kill/reset: std_srvs/srv/Empty/spawn: turtlesim/srv/Spawn/turtle1/set_pen: turtlesim/srv/SetPen/turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute/turtle1/teleport_relative: turtlesim/srv/TeleportRelative/turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters/turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes/turtlesim/get_parameters: rcl_interfaces/srv/GetParameters/turtlesim/list_parameters: rcl_interfaces/srv/ListParameters/turtlesim/set_parameters: rcl_interfaces/srv/SetParameters/turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomicallyService Clients:Action Servers:/turtle1/rotate_absolute: turtlesim/action/RotateAbsoluteAction Clients: + +Language: unknown +ros2 node info /teleop_turtle + +Language: unknown +/teleop_turtleSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEventPublishers:/parameter_events: rcl_interfaces/msg/ParameterEvent/rosout: rcl_interfaces/msg/Log/turtle1/cmd_vel: geometry_msgs/msg/TwistService Servers:/teleop_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters/teleop_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes/teleop_turtle/get_parameters: rcl_interfaces/srv/GetParameters/teleop_turtle/list_parameters: rcl_interfaces/srv/ListParameters/teleop_turtle/set_parameters: rcl_interfaces/srv/SetParameters/teleop_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomicallyService Clients:Action Servers:Action Clients:/turtle1/rotate_absolute: turtlesim/action/RotateAbsolute + +Language: unknown +ros2 action list + +Language: unknown +/turtle1/rotate_absolute + +Language: unknown +ros2 action list -t + +Language: unknown +/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute] + +Language: unknown +ros2 action type /turtle1/rotate_absolute + +Language: unknown +turtlesim/action/RotateAbsolute + +Language: unknown +ros2 action info /turtle1/rotate_absolute + +Language: unknown +Action: /turtle1/rotate_absoluteAction clients: 1/teleop_turtleAction servers: 1/turtlesim + +Language: unknown +ros2 interface show turtlesim/action/RotateAbsolute + +Language: unknown +#Thedesiredheadinginradiansfloat32 theta---#Theangulardisplacementinradianstothestartingpositionfloat32 delta---#Theremainingrotationinradiansfloat32 remaining + +Language: unknown +ros2 action send_goal + +Language: unknown +ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}" + +Language: unknown +Waiting for an action server to become available...Sending goal:theta: 1.57Goal accepted with ID: f8db8f44410849eaa93d3feb747dd444Result:delta: -1.568000316619873Goal finished with status: SUCCEEDED + +Language: unknown +ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback + +Language: unknown +Sending goal:theta: -1.57Goal accepted with ID: e6092c831f994afda92f0086f220da27Feedback:remaining: -3.1268222332000732Feedback:remaining: -3.1108222007751465…Result:delta: 3.1200008392333984Goal finished with status: SUCCEEDED diff --git "a/exported_docs/ros2/Understanding_nodes\357\203\201.txt" "b/exported_docs/ros2/Understanding_nodes\357\203\201.txt" new file mode 100644 index 0000000..ca489b7 --- /dev/null +++ "b/exported_docs/ros2/Understanding_nodes\357\203\201.txt" @@ -0,0 +1,53 @@ +Title: Understanding nodes +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Nodes/Understanding-ROS2-Nodes.html +Section: Installation +-------------------------------------------------------------------------------- + +Understanding nodesGoal:Learn about the function of nodes in ROS 2, and the tools to interact with them.Tutorial level:BeginnerTime:10 minutesContentsBackground1 The ROS 2 graph2 Nodes in ROS 2PrerequisitesTasks1 ros2 run2 ros2 node list3 ros2 node infoSummaryNext stepsRelated contentBackground1 The ROS 2 graphOver the next few tutorials, you will learn about a series of core ROS 2 concepts that make up what is referred to as the “ROS (2) graph”.The ROS graph is a network of ROS 2 elements processing data together at the same time. +It encompasses all executables and the connections between them if you were to map them all out and visualize them.2 Nodes in ROS 2Each node in ROS should be responsible for a single, modular purpose, e.g. controlling the wheel motors or publishing the sensor data from a laser range-finder. +Each node can send and receive data from other nodes via topics, services, actions, or parameters.A full robotic system is comprised of many nodes working in concert. +In ROS 2, a single executable (C++ program, Python program, etc.) can contain one or more nodes.PrerequisitesTheprevious tutorialshows you how to install theturtlesimpackage used here.As always, don’t forget to source ROS 2 inevery new terminal you open.Tasks1 ros2 runThe commandros2runlaunches an executable from a package.ros2 run To run turtlesim, open a new terminal, and enter the following command:ros2 run turtlesim turtlesim_nodeThe turtlesim window will open, as you saw in theprevious tutorial.Here, the package name isturtlesimand the executable name isturtlesim_node.We still don’t know the node name, however. +You can find node names by usingros2nodelist2 ros2 node listros2nodelistwill show you the names of all running nodes. +This is especially useful when you want to interact with a node, or when you have a system running many nodes and need to keep track of them.Open a new terminal while turtlesim is still running in the other one, and enter the following command:ros2 node listThe terminal will return the node name:/turtlesimOpen another new terminal and start the teleop node with the command:ros2 run turtlesim turtle_teleop_keyHere, we are referring to theturtlesimpackage again, but this time we target the executable namedturtle_teleop_key.Return to the terminal where you ranros2nodelistand run it again. +You will now see the names of two active nodes:/turtlesim/teleop_turtle2.1 RemappingRemappingallows you to reassign default node properties, like node name, topic names, service names, etc., to custom values. +In the last tutorial, you used remapping onturtle_teleop_keyto change the cmd_vel topic and targetturtle2.Now, let’s reassign the name of our/turtlesimnode. +In a new terminal, run the following command:ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtleSince you’re callingros2runon turtlesim again, another turtlesim window will open. +However, now if you return to the terminal where you ranros2nodelist, and run it again, you will see three node names:/my_turtle/turtlesim/teleop_turtle3 ros2 node infoNow that you know the names of your nodes, you can access more information about them with:ros2 node info To examine your latest node,my_turtle, run the following command:ros2 node info /my_turtleros2nodeinforeturns a list of subscribers, publishers, services, and actions. i.e. the ROS graph connections that interact with that node. +The output should look like this:/my_turtleSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEvent/turtle1/cmd_vel: geometry_msgs/msg/TwistPublishers:/parameter_events: rcl_interfaces/msg/ParameterEvent/rosout: rcl_interfaces/msg/Log/turtle1/color_sensor: turtlesim/msg/Color/turtle1/pose: turtlesim/msg/PoseService Servers:/clear: std_srvs/srv/Empty/kill: turtlesim/srv/Kill/my_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters/my_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes/my_turtle/get_parameters: rcl_interfaces/srv/GetParameters/my_turtle/list_parameters: rcl_interfaces/srv/ListParameters/my_turtle/set_parameters: rcl_interfaces/srv/SetParameters/my_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically/reset: std_srvs/srv/Empty/spawn: turtlesim/srv/Spawn/turtle1/set_pen: turtlesim/srv/SetPen/turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute/turtle1/teleport_relative: turtlesim/srv/TeleportRelativeService Clients:Action Servers:/turtle1/rotate_absolute: turtlesim/action/RotateAbsoluteAction Clients:Now try running the same command on the/teleop_turtlenode, and see how its connections differ frommy_turtle.You will learn more about the ROS graph connection concepts including the message types in the upcoming tutorials.SummaryA node is a fundamental ROS 2 element that serves a single, modular purpose in a robotics system.In this tutorial, you utilized nodes created in theturtlesimpackage by running the executablesturtlesim_nodeandturtle_teleop_key.You learned how to useros2nodelistto discover active node names andros2nodeinfoto introspect a single node. +These tools are vital to understanding the flow of data in a complex, real-world robot system.Next stepsNow that you understand nodes in ROS 2, you can move on to thetopics tutorial. +Topics are one of the communication types that connects nodes.Related contentTheConceptspage adds some more detail to the concept of nodes. + +Code Examples: + +Language: unknown +ros2 run + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 node list + +Language: unknown +/turtlesim + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +/turtlesim/teleop_turtle + +Language: unknown +ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle + +Language: unknown +/my_turtle/turtlesim/teleop_turtle + +Language: unknown +ros2 node info + +Language: unknown +ros2 node info /my_turtle + +Language: unknown +/my_turtleSubscribers:/parameter_events: rcl_interfaces/msg/ParameterEvent/turtle1/cmd_vel: geometry_msgs/msg/TwistPublishers:/parameter_events: rcl_interfaces/msg/ParameterEvent/rosout: rcl_interfaces/msg/Log/turtle1/color_sensor: turtlesim/msg/Color/turtle1/pose: turtlesim/msg/PoseService Servers:/clear: std_srvs/srv/Empty/kill: turtlesim/srv/Kill/my_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters/my_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes/my_turtle/get_parameters: rcl_interfaces/srv/GetParameters/my_turtle/list_parameters: rcl_interfaces/srv/ListParameters/my_turtle/set_parameters: rcl_interfaces/srv/SetParameters/my_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically/reset: std_srvs/srv/Empty/spawn: turtlesim/srv/Spawn/turtle1/set_pen: turtlesim/srv/SetPen/turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute/turtle1/teleport_relative: turtlesim/srv/TeleportRelativeService Clients:Action Servers:/turtle1/rotate_absolute: turtlesim/action/RotateAbsoluteAction Clients: diff --git "a/exported_docs/ros2/Understanding_parameters\357\203\201.txt" "b/exported_docs/ros2/Understanding_parameters\357\203\201.txt" new file mode 100644 index 0000000..4ba10fa --- /dev/null +++ "b/exported_docs/ros2/Understanding_parameters\357\203\201.txt" @@ -0,0 +1,71 @@ +Title: Understanding parameters +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Parameters/Understanding-ROS2-Parameters.html +Section: Installation +-------------------------------------------------------------------------------- + +Understanding parametersGoal:Learn how to get, set, save and reload parameters in ROS 2.Tutorial level:BeginnerTime:5 minutesContentsBackgroundPrerequisitesTasks1 Setup2 ros2 param list3 ros2 param get4 ros2 param set5 ros2 param dump6 ros2 param load7 Load parameter file on node startupSummaryNext stepsBackgroundA parameter is a configuration value of a node. +You can think of parameters as node settings. +A node can store parameters as integers, floats, booleans, strings, and lists. +In ROS 2, each node maintains its own parameters. +For more background on parameters, please seethe concept document.PrerequisitesThis tutorial uses theturtlesim package.As always, don’t forget to source ROS 2 inevery new terminal you open.Tasks1 SetupStart up the two turtlesim nodes,/turtlesimand/teleop_turtle.Open a new terminal and run:ros2 run turtlesim turtlesim_nodeOpen another terminal and run:ros2 run turtlesim turtle_teleop_key2 ros2 param listTo see the parameters belonging to your nodes, open a new terminal and enter the command:ros2 param listYou will see the node namespaces,/teleop_turtleand/turtlesim, followed by each node’s parameters:/teleop_turtle:qos_overrides./parameter_events.publisher.depthqos_overrides./parameter_events.publisher.durabilityqos_overrides./parameter_events.publisher.historyqos_overrides./parameter_events.publisher.reliabilityscale_angularscale_linearuse_sim_time/turtlesim:background_bbackground_gbackground_rqos_overrides./parameter_events.publisher.depthqos_overrides./parameter_events.publisher.durabilityqos_overrides./parameter_events.publisher.historyqos_overrides./parameter_events.publisher.reliabilityuse_sim_timeEvery node has the parameteruse_sim_time; it’s not unique to turtlesim.Based on their names, it looks like/turtlesim’s parameters determine the background color of the turtlesim window using RGB color values.To determine a parameter’s type, you can useros2paramget.3 ros2 param getTo display the type and current value of a parameter, use the command:ros2 param get Let’s find out the current value of/turtlesim’s parameterbackground_g:ros2 param get /turtlesim background_gWhich will return the value:Integer value is: 86Now you knowbackground_gholds an integer value.If you run the same command onbackground_randbackground_b, you will get the values69and255, respectively.4 ros2 param setTo change a parameter’s value at runtime, use the command:ros2 param set Let’s change/turtlesim’s background color:ros2 param set /turtlesim background_r 150Your terminal should return the message:Set parameter successfulAnd the background of your turtlesim window should change colors:Setting parameters with thesetcommand will only change them in your current session, not permanently. +However, you can save your settings and reload them the next time you start a node.5 ros2 param dumpYou can view all of a node’s current parameter values by using the command:ros2 param dump The command prints to the standard output (stdout) by default but you can also redirect the parameter values into a file to save them for later. +To save your current configuration of/turtlesim’s parameters into the fileturtlesim.yaml, enter the command:ros2 param dump /turtlesim > turtlesim.yamlYou will find a new file in the current working directory your shell is running in. +If you open this file, you’ll see the following content:/turtlesim:ros__parameters:background_b:255background_g:86background_r:150qos_overrides:/parameter_events:publisher:depth:1000durability:volatilehistory:keep_lastreliability:reliableuse_sim_time:falseDumping parameters comes in handy if you want to reload the node with the same parameters in the future.6 ros2 param loadYou can load parameters from a file to a currently running node using the command:ros2 param load To load theturtlesim.yamlfile generated withros2paramdumpinto/turtlesimnode’s parameters, enter the command:ros2 param load /turtlesim turtlesim.yamlYour terminal will return the message:Set parameter background_b successfulSet parameter background_g successfulSet parameter background_r successfulSet parameter qos_overrides./parameter_events.publisher.depth failed: parameter 'qos_overrides./parameter_events.publisher.depth' cannot be set because it is read-onlySet parameter qos_overrides./parameter_events.publisher.durability failed: parameter 'qos_overrides./parameter_events.publisher.durability' cannot be set because it is read-onlySet parameter qos_overrides./parameter_events.publisher.history failed: parameter 'qos_overrides./parameter_events.publisher.history' cannot be set because it is read-onlySet parameter qos_overrides./parameter_events.publisher.reliability failed: parameter 'qos_overrides./parameter_events.publisher.reliability' cannot be set because it is read-onlySet parameter use_sim_time successfulNoteRead-only parameters can only be modified at startup and not afterwards, that is why there are some warnings for the “qos_overrides” parameters.7 Load parameter file on node startupTo start the same node using your saved parameter values, use:ros2 run --ros-args --params-file This is the same command you always use to start turtlesim, with the added flags--ros-argsand--params-file, followed by the file you want to load.Stop your running turtlesim node, and try reloading it with your saved parameters, using:ros2 run turtlesim turtlesim_node --ros-args --params-file turtlesim.yamlThe turtlesim window should appear as usual, but with the purple background you set earlier.NoteWhen a parameter file is used at node startup, all parameters, including the read-only ones, will be updated.SummaryNodes have parameters to define their default configuration values. +You cangetandsetparameter values from the command line. +You can also save the parameter settings to a file to reload them in a future session.Next stepsJumping back to ROS 2 communication methods, in the next tutorial you’ll learn aboutactions. + +Code Examples: + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +ros2 param list + +Language: unknown +/teleop_turtle:qos_overrides./parameter_events.publisher.depthqos_overrides./parameter_events.publisher.durabilityqos_overrides./parameter_events.publisher.historyqos_overrides./parameter_events.publisher.reliabilityscale_angularscale_linearuse_sim_time/turtlesim:background_bbackground_gbackground_rqos_overrides./parameter_events.publisher.depthqos_overrides./parameter_events.publisher.durabilityqos_overrides./parameter_events.publisher.historyqos_overrides./parameter_events.publisher.reliabilityuse_sim_time + +Language: unknown +ros2 param get + +Language: unknown +ros2 param get /turtlesim background_g + +Language: unknown +Integer value is: 86 + +Language: unknown +ros2 param set + +Language: unknown +ros2 param set /turtlesim background_r 150 + +Language: unknown +Set parameter successful + +Language: unknown +ros2 param dump + +Language: unknown +ros2 param dump /turtlesim > turtlesim.yaml + +Language: unknown +/turtlesim:ros__parameters:background_b:255background_g:86background_r:150qos_overrides:/parameter_events:publisher:depth:1000durability:volatilehistory:keep_lastreliability:reliableuse_sim_time:false + +Language: unknown +ros2 param load + +Language: unknown +ros2 param load /turtlesim turtlesim.yaml + +Language: unknown +Set parameter background_b successfulSet parameter background_g successfulSet parameter background_r successfulSet parameter qos_overrides./parameter_events.publisher.depth failed: parameter 'qos_overrides./parameter_events.publisher.depth' cannot be set because it is read-onlySet parameter qos_overrides./parameter_events.publisher.durability failed: parameter 'qos_overrides./parameter_events.publisher.durability' cannot be set because it is read-onlySet parameter qos_overrides./parameter_events.publisher.history failed: parameter 'qos_overrides./parameter_events.publisher.history' cannot be set because it is read-onlySet parameter qos_overrides./parameter_events.publisher.reliability failed: parameter 'qos_overrides./parameter_events.publisher.reliability' cannot be set because it is read-onlySet parameter use_sim_time successful + +Language: unknown +ros2 run --ros-args --params-file + +Language: unknown +ros2 run turtlesim turtlesim_node --ros-args --params-file turtlesim.yaml diff --git "a/exported_docs/ros2/Understanding_real-time_programming\357\203\201.txt" "b/exported_docs/ros2/Understanding_real-time_programming\357\203\201.txt" new file mode 100644 index 0000000..9bfd29d --- /dev/null +++ "b/exported_docs/ros2/Understanding_real-time_programming\357\203\201.txt" @@ -0,0 +1,66 @@ +Title: Understanding real-time programming +URL: https://docs.ros.org/en/jazzy/Tutorials/Demos/Real-Time-Programming.html +Section: Installation +-------------------------------------------------------------------------------- + +Understanding real-time programmingTable of ContentsBackgroundInstall and run the demoRun the testsWhat the heck just happened?Adjust permissions for memory lockingOutput overviewLatencySetting permissions for the schedulerPlotting resultsBackgroundReal-time computing is a key feature of many robotics systems, particularly safety- and mission-critical applications such as autonomous vehicles, spacecrafts, and industrial manufacturing. +We are designing and prototyping ROS 2 with real-time performance constraints in mind, since this is a requirement that was not considered in the early stages of ROS 1 and it is now intractable to refactor ROS 1 to be real-time friendly.This documentoutlines the requirements of real-time computing and best practices for software engineers. In short:To make a real-time computer system, our real-time loop must update periodically to meet deadlines. +We can only tolerate a small margin of error on these deadlines (our maximum allowable jitter). +To do this, we must avoid nondeterministic operations in the execution path, things like: pagefault events, dynamic memory allocation/deallocation, and synchronization primitives that block indefinitely.A classic example of a controls problem commonly solved by real-time computing is balancing aninverted pendulum. +If the controller blocked for an unexpectedly long amount of time, the pendulum would fall down or go unstable. +But if the controller reliably updates at a rate faster than the motor controlling the pendulum can operate, the pendulum will successfully adapt react to sensor data to balance the pendulum.Now that you know everything about real-time computing, let’s try a demo!Install and run the demoThe real-time demo was written with Linux operating systems in mind, since many members of the ROS community doing real-time computing use Xenomai or RT_PREEMPT as their real-time solutions. +Since many of the operations done in the demo to optimize performance are OS-specific, the demo only builds and runs on Linux systems.So, if you are an OSX or Windows user, don’t try this part!Also this must be built from source using a static DDS API.Currently the only supported implementation is Connext.First, follow the instructions to build ROS 2from sourceusing Connext DDS as the middleware.Run the testsBefore you run make sure you have at least 8Gb of RAM free. With the memory locking, swap will not work anymore.Source your ROS 2 setup.bash.Run the demo binary, and redirect the output. You may want to usesudoin case you get permission error:pendulum_demo>output.txtWhat the heck just happened?First, even though you redirected stdout, you will see some output to the console (from stderr):mlockallfailed:CannotallocatememoryCouldn't lock all cached virtual memory.PagefaultsfromreadingpagesnotyetmappedintoRAMwillberecorded.After the initialization stage of the demo program, it will attempt to lock all cached memory into RAM and prevent future dynamic memory allocations usingmlockall. +This is to prevent pagefaults from loading lots of new memory into RAM. +(Seethe realtime design articlefor more information.)The demo will continue on as usual when this occurs. +At the bottom of the output.txt file generated by the demo, you’ll see the number of pagefaults encountered during execution:rtteststatistics:-Minorpagefaults:20-Majorpagefaults:0If we want those pagefaults to go away, we’ll have to…Adjust permissions for memory lockingAdd to/etc/security/limits.conf(as sudo):-memlockA limit of-1is unlimited. +If you choose this, you may need to accompany it withulimit-lunlimited(as root) after editing the file.After saving the file, log out and log back in. +Then rerun thependulum_demoinvocation.You’ll either see zero pagefaults in your output file, or an error saying that a bad_alloc exception was caught. +If this happened, you didn’t have enough free memory available to lock the memory allocated for the process into RAM. +You’ll need to install more RAM in your computer to see zero pagefaults!Output overviewTo see more output, we have to run thependulum_loggernode.In one shell with yourinstall/setup.bashsourced, invoke:pendulum_loggerYou should see the output message:Loggernodeinitialized.In another shell with setup.bash sourced, invokependulum_demoagain.As soon as this executable starts, you should see the other shell constantly printing output:Commandedmotorangle:1.570796Actualmotorangle:1.570796Meanlatency:210144.000000nsMinlatency:4805nsMaxlatency:578137nsMinorpagefaultsduringexecution:0Majorpagefaultsduringexecution:0The demo is controlling a very simple inverted pendulum simulation. +The pendulum simulation calculates its position in its own thread. +A ROS node simulates a motor encoder sensor for the pendulum and publishes its position. +Another ROS node acts as a simple PID controller and calculates the next command message.The logger node periodically prints out the pendulum’s state and the runtime performance statistics of the demo during its execution phase.After thependulum_demois finished, you’ll have to CTRL-C out of the logger node to exit.LatencyAt thependulum_demoexecution, you’ll see the final statistics collected for the demo:rtteststatistics:-Minorpagefaults:0-Majorpagefaults:0Latency(timeafterdeadlinewasmissed):-Min:3354ns-Max:2752187ns-Mean:19871.8ns-Standarddeviation:1.35819e+08PendulumMotorreceived985messagesPendulumControllerreceived987messagesThe latency fields show you the minimum, maximum, and average latency of the update loop in nanoseconds. +Here, latency means the amount of time after the update was expected to occur.The requirements of a real-time system depend on the application, but let’s say in this demo we have a 1kHz (1 millisecond) update loop, and we’re aiming for a maximum allowable latency of 5% of our update period.So, our average latency was really good in this run, but the maximum latency was unacceptable because it actually exceeded our update loop! What happened?We may be suffering from a non-deterministic scheduler. +If you’re running a vanilla Linux system and you don’t have the RT_PREEMPT kernel installed, you probably won’t be able to meet the real-time goal we set for ourselves, because the Linux scheduler won’t allow you to arbitrarily pre-empt threads at the user level.See therealtime design articlefor more information.The demo attempts to set the scheduler and thread priority of the demo to be suitable for real-time performance. +If this operation failed, you’ll see an error message: “Couldn’t set scheduling priority and policy: Operation not permitted”. +You can get slightly better performance by following the instructions in the next section:Setting permissions for the schedulerAdd to/etc/security/limits.conf(as sudo):-rtprio98The range of the rtprio (real-time priority) field is 0-99. +However, do NOT set the limit to 99 because then your processes could interfere with important system processes that run at the top priority (e.g. watchdog). +This demo will attempt to run the control loop at priority 98.Plotting resultsYou can plot the latency and pagefault statistics that are collected in this demo after the demo runs.Because the code has been instrumented withrttest, there are useful command line arguments available:CommandDescriptionDefault value-iSpecify how many iterations to run the real-time loop1000-uSpecify the update period with the default unit being microseconds.Use the suffix “s” for seconds, “ms” for milliseconds,“us” for microseconds, and “ns” for nanoseconds.1ms-fSpecify the name of the file for writing the collected data.Run the demo again with a filename to save results:pendulum_demo-fpendulum_demo_resultsThen run therttest_plotscript on the resulting file:ros2runrttestrttest_plotpendulum_demo_resultsThis script will produce a number of files:pendulum_demo_results_plot_latency.svgpendulum_demo_results_plot_latency_hist.svgpendulum_demo_results_plot_majflts.svgpendulum_demo_results_plot_minflts.svgYou can view these plots in an image viewer of your choice. + +Code Examples: + +Language: unknown +pendulum_demo>output.txt + +Language: unknown +mlockallfailed:CannotallocatememoryCouldn't lock all cached virtual memory.PagefaultsfromreadingpagesnotyetmappedintoRAMwillberecorded. + +Language: unknown +rtteststatistics:-Minorpagefaults:20-Majorpagefaults:0 + +Language: unknown +-memlock + +Language: unknown +pendulum_logger + +Language: unknown +Loggernodeinitialized. + +Language: unknown +Commandedmotorangle:1.570796Actualmotorangle:1.570796Meanlatency:210144.000000nsMinlatency:4805nsMaxlatency:578137nsMinorpagefaultsduringexecution:0Majorpagefaultsduringexecution:0 + +Language: unknown +rtteststatistics:-Minorpagefaults:0-Majorpagefaults:0Latency(timeafterdeadlinewasmissed):-Min:3354ns-Max:2752187ns-Mean:19871.8ns-Standarddeviation:1.35819e+08PendulumMotorreceived985messagesPendulumControllerreceived987messages + +Language: unknown +-rtprio98 + +Language: unknown +pendulum_demo-fpendulum_demo_results + +Language: unknown +ros2runrttestrttest_plotpendulum_demo_results + +Language: unknown +pendulum_demo_results_plot_latency.svgpendulum_demo_results_plot_latency_hist.svgpendulum_demo_results_plot_majflts.svgpendulum_demo_results_plot_minflts.svg diff --git "a/exported_docs/ros2/Understanding_the_security_keystore\357\203\201.txt" "b/exported_docs/ros2/Understanding_the_security_keystore\357\203\201.txt" new file mode 100644 index 0000000..934c070 --- /dev/null +++ "b/exported_docs/ros2/Understanding_the_security_keystore\357\203\201.txt" @@ -0,0 +1,71 @@ +Title: Understanding the security keystore +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Security/The-Keystore.html +Section: Installation +-------------------------------------------------------------------------------- + +Understanding the security keystoreGoal:Explore files located in the ROS 2 security keystore.Tutorial level:AdvancedTime:15 minutesContentsBackgroundSecurity Artifact LocationsPublic Key MaterialsPrivate Key MaterialsDomain Governance PolicySecurity EnclavesTake the quiz!BackgroundBefore proceeding ensure you have completed theSetting up securitytutorial.Thesros2package can be used to create keys, certificates and policies necessary to enable ROS 2 security. +However, the security configuration is extrememly flexible. +A basic understanding of the ROS 2 Security Keystore will allow integration with an existing PKI (Public Key Infrastructure) and managment of sensitive key materials consistent with organizational policies.Security Artifact LocationsWith communications security enabled in the prior tutorial, let’s take a look at the files which were created when security was enabled. +These are the files which make encryption possible.Thesros2utilities (ros2security...) separate files into public, private and enclave key materials.ROS uses the directory defined by the environmental variableROS_SECURITY_KEYSTOREas the keystore. +For this tutorial, we use the directory~/sros2_demo/demo_keystore.Public Key MaterialsYou will find three encryption certificates in the public directory at~/sros2_demo/demo_keystore/public; however, the identity and permissions certificates are actually just a link to the Certificate Authority (CA) certificate.In a public key infrastructure, theCertificate Authorityacts as a trust anchor: it validates the identities and permissions of participants. +For ROS, that means all the nodes that participate in the ROS graph (which may extend to an entire fleet of individual robots). +By placing the Certificate Authority’s certificate (ca.cert.pem) in the proper location on the robot, all ROS nodes can establish mutual trust with other nodes using the same Certificate Authority.Although in our tutorials we create a Certificate Authority on-the-fly, in a production system this should be done according to a pre-defined security plan. +Typically the Certificate Authority for a production system will be created off-line, and placed on the robot during initial setup. +It may be unique for each robot, or shared across a fleet of robots all intended to trust each other.DDS (and ROS, by extension) supports separation of identity and permission trust chains, so each function has its own certificate authority. +In most cases a ROS system security plan does not require a separation between these duties, so the security utilities generate a single Certificate Authority which is used for both identity and permissions.Useopensslto view this x509 certificate and display it as text:cd~/sros2_demo/demo_keystore/public +opensslx509-inca.cert.pem-text-nooutThe output should look similar to the following:Certificate:Data:Version:3(0x2)SerialNumber:02:8e:9a:24:ea:10:55:cb:e6:ea:e8:7a:c0:5f:58:6d:37:42:78:aaSignatureAlgorithm:ecdsa-with-SHA256Issuer:CN=sros2CAValidityNotBefore:Jun116:57:372021GMTNotAfter:May3116:57:372031GMTSubject:CN=sros2CASubjectPublicKeyInfo:PublicKeyAlgorithm:id-ecPublicKeyPublic-Key:(256bit)pub:04:71:e9:37:d7:32:ba:b8:a0:97:66:da:9f:e3:c4:08:4f:7a:13:59:24:c6:cf:6a:f7:95:c5:cd:82:c0:7f:7f:e3:90:dd:7b:0f:77:d1:ee:0e:af:68:7c:76:a9:ca:60:d7:1e:2c:01:d7:bc:7e:e3:86:2a:9f:38:dc:ed:39:c5:32ASN1OID:prime256v1NISTCURVE:P-256X509v3extensions:X509v3BasicConstraints:criticalCA:TRUE,pathlen:1SignatureAlgorithm:ecdsa-with-SHA25630:45:02:21:00:d4:fc:d8:45:ff:a4:51:49:98:4c:f0:c4:3f:e0:e7:33:19:8e:31:3c:d0:43:e7:e9:8f:36:f0:90:18:ed:d7:7d:02:20:30:84:f7:04:33:87:bb:4f:d3:8b:95:61:48:df:83:4b:e5:92:b3:e6:ee:3c:d5:cf:30:43:09:04:71:bd:dd:7cSome things to note about this CA certificate:The certificate subject namesros2CAis the default provided by thesros2utilities.This certificate is valid for ten years from time of creationLike all certificates, this contains a public key used for public-private key encryptionAs a Root Certificate Authority, this is aself-signed certificate; i.e., it is signed using its own private key.Since this is a public certificate, it can be freely copied as needed to establish trust throughout your ROS system.Private Key MaterialsPrivate key materials can be found in the keystore directory~/sros2_demo/demo_keystore/private. +Similar to thepublicdirectory, this contains one certificate authority keyca.key.pemand symbolic links to it to be used as both an Identity and a Permissions CA private key.WarningProtect this private key and create a secure backup of it!This is the private key associated with the public Certificate Authority which serves as the anchor for all security in your ROS system. +You will use it to modify encryption policies for the ROS graph and to add new ROS participants. +Depending upon your robot’s security needs, the key can be protected with access permissions and locked down to another account, or it can be moved off the robot entirely and onto another system or device. +If the file is lost, you will be unable to change access permissions and add new participants to the system. +Similarly, any user or process with access to the file has the ability to modify system policies and participants.This file is only required for configuring the robot, but is not needed for the robot to run. +It can safely be stored offline in another system or removable media.Thesros2utilities useelliptic curve cryptograpyrather than RSA for improved security and reduced key size. +Use the following command to show details about this elliptic curve private key:cd~/sros2_demo/demo_keystore/private +opensslec-inca.key.pem-text-nooutYour output should look similar to the following:readECkeyPrivate-Key:(256bit)priv:93:da:76:b9:e3:91:ab:e9:42:76:f2:38:f1:9d:94:90:5e:b5:96:7b:7f:71:ee:13:1b:d4:a0:f9:48:fb:ae:77pub:04:71:e9:37:d7:32:ba:b8:a0:97:66:da:9f:e3:c4:08:4f:7a:13:59:24:c6:cf:6a:f7:95:c5:cd:82:c0:7f:7f:e3:90:dd:7b:0f:77:d1:ee:0e:af:68:7c:76:a9:ca:60:d7:1e:2c:01:d7:bc:7e:e3:86:2a:9f:38:dc:ed:39:c5:32ASN1OID:prime256v1NISTCURVE:P-256In addition to the private key itself, note that the public key is listed, and it matches the public key listed in the Certificate Authorityca.cert.pem.Domain Governance PolicyFind the domain governance policy in the enclave directory within the keystore,~/sros2_demo/demo_keystore/enclaves. +Theenclavedirectory contains XML governance policy documentgovernance.xml, as well as a copy of the document which has been signed by the Permissions CA asgovernance.p7s.Thegovernance.p7sfile contains domain-wide settings such as how to handle unauthenticated participants, whether to encrypt discovery, and default rules for access to topics.Use the following command to validate theS/MIME signatureof the governance file:opensslsmime-verify-ingovernance.p7s-CAfile../public/permissions_ca.cert.pemThis command will print out the XML document, and the last line will beVerificationsuccessfulto show that the document was properly signed by the Permissions CA.Security EnclavesSecure processes (typically ROS nodes) run within a security enclave. +In the simplest case, all the processes can be consolidated into the same enclave, and all processes will then use the same security policy. +However, to apply different policies to different processes, the processes can use different security enclaves when starting. +For more details about security enclaves, see thedesign document. +The security enclave is specifed by using the ROS argument--enclavewhen running a node.Each security enclave requires six filesin order to enable security. +Each filemustbe named as defined below, and as outlined in theDDS Security standard. +In order to avoid having mulitple copies of the same files, thesros2utilities create links for each enclave to the single governance policy, the Identity CA and Permissions CA descibed above.See the following six files within thelistenerenclave. +Three are specific to this enclave, while three are generic to this ROS system:key.pem, the private key used to encrypt and decrypt within this enclavecert.pem, the public certificate for this enclave; this certificate has been signed by the Identity CApermissions.p7s, the permissions for this enclave; this file has been signed with the Permissions CAgovernance.p7s, a link to the signed security policy file for this domainidentity_ca.cert.pem, a link to the Identity CA for this domainpermissions_ca.cert.pem, a link to the Permissions CA for this domainThe private encryption keykey.pemshould be protected according to your security plan. +This key encrypts, decrypts and validates communications within this specific enclave. +Should the key be lost or stolen, revoke the key and create a new identity for this enclave.The filepermissions.xmlhas also been created in this directory and can be used to recreate the signed permissions file. +However, this file is not required to enable security since DDS uses the signed version of the file instead.Take the quiz!See if you can answer these questions about the ROS security keystore. +Begin with a new terminal session and enable security with the keystore created in the prior tutorial:exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforcecd~/sros2_demo/demo_keystore/enclaves/talker_listener/listenerMake a backup copy ofpermissions.p7sbefore beginning.Question 1Answer 1Openpermissions.p7sin a text editor. Make a negligible change to the XML content (e.g., add a space or a blank line) and save the file. +Launch the listener node:ros2rundemo_nodes_cpplistener--ros-args--enclave/talker_listener/listenerWhat do you expect to happen?Can you launch the talker node?ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talkerWhat is the difference between launching the listener and launching the talker?The listener fails to launch and throws an error. +When thepermissions.p7sfile was modified–however minor–the file’s signature became invalid. +A node will not launch with security enabled and enforced when the permissions file is invalid.The talker will start as expected. +It uses thepermissions.p7sfile in a different enclave, and the file is still valid.Question 2Answer 2What command lets you check to see if the signature on the modifiedpermissions.p7sfile is valid?Check thatpermissions.p7shas been properly signed by the Permissions CA using theopensslsmimecommand:opensslsmime-verify-inpermissions.p7s-CAfilepermissions_ca.cert.pemRestore your original, properly signedpermissions.p7sfile before proceeding to the next tutorial. + +Code Examples: + +Language: unknown +cd~/sros2_demo/demo_keystore/public +opensslx509-inca.cert.pem-text-noout + +Language: unknown +Certificate:Data:Version:3(0x2)SerialNumber:02:8e:9a:24:ea:10:55:cb:e6:ea:e8:7a:c0:5f:58:6d:37:42:78:aaSignatureAlgorithm:ecdsa-with-SHA256Issuer:CN=sros2CAValidityNotBefore:Jun116:57:372021GMTNotAfter:May3116:57:372031GMTSubject:CN=sros2CASubjectPublicKeyInfo:PublicKeyAlgorithm:id-ecPublicKeyPublic-Key:(256bit)pub:04:71:e9:37:d7:32:ba:b8:a0:97:66:da:9f:e3:c4:08:4f:7a:13:59:24:c6:cf:6a:f7:95:c5:cd:82:c0:7f:7f:e3:90:dd:7b:0f:77:d1:ee:0e:af:68:7c:76:a9:ca:60:d7:1e:2c:01:d7:bc:7e:e3:86:2a:9f:38:dc:ed:39:c5:32ASN1OID:prime256v1NISTCURVE:P-256X509v3extensions:X509v3BasicConstraints:criticalCA:TRUE,pathlen:1SignatureAlgorithm:ecdsa-with-SHA25630:45:02:21:00:d4:fc:d8:45:ff:a4:51:49:98:4c:f0:c4:3f:e0:e7:33:19:8e:31:3c:d0:43:e7:e9:8f:36:f0:90:18:ed:d7:7d:02:20:30:84:f7:04:33:87:bb:4f:d3:8b:95:61:48:df:83:4b:e5:92:b3:e6:ee:3c:d5:cf:30:43:09:04:71:bd:dd:7c + +Language: unknown +cd~/sros2_demo/demo_keystore/private +opensslec-inca.key.pem-text-noout + +Language: unknown +readECkeyPrivate-Key:(256bit)priv:93:da:76:b9:e3:91:ab:e9:42:76:f2:38:f1:9d:94:90:5e:b5:96:7b:7f:71:ee:13:1b:d4:a0:f9:48:fb:ae:77pub:04:71:e9:37:d7:32:ba:b8:a0:97:66:da:9f:e3:c4:08:4f:7a:13:59:24:c6:cf:6a:f7:95:c5:cd:82:c0:7f:7f:e3:90:dd:7b:0f:77:d1:ee:0e:af:68:7c:76:a9:ca:60:d7:1e:2c:01:d7:bc:7e:e3:86:2a:9f:38:dc:ed:39:c5:32ASN1OID:prime256v1NISTCURVE:P-256 + +Language: unknown +opensslsmime-verify-ingovernance.p7s-CAfile../public/permissions_ca.cert.pem + +Language: unknown +exportROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystoreexportROS_SECURITY_ENABLE=trueexportROS_SECURITY_STRATEGY=Enforcecd~/sros2_demo/demo_keystore/enclaves/talker_listener/listener + +Language: unknown +ros2rundemo_nodes_cpplistener--ros-args--enclave/talker_listener/listener + +Language: unknown +ros2rundemo_nodes_cpptalker--ros-args--enclave/talker_listener/talker + +Language: unknown +opensslsmime-verify-inpermissions.p7s-CAfilepermissions_ca.cert.pem diff --git "a/exported_docs/ros2/Understanding_topics\357\203\201.txt" "b/exported_docs/ros2/Understanding_topics\357\203\201.txt" new file mode 100644 index 0000000..1324a5b --- /dev/null +++ "b/exported_docs/ros2/Understanding_topics\357\203\201.txt" @@ -0,0 +1,117 @@ +Title: Understanding topics +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Topics/Understanding-ROS2-Topics.html +Section: Installation +-------------------------------------------------------------------------------- + +Understanding topicsGoal:Use rqt_graph and command line tools to introspect ROS 2 topics.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Setup2 rqt_graph3 ros2 topic list4 ros2 topic echo5 ros2 topic info6 ros2 interface show7 ros2 topic pub8 ros2 topic hz9 ros2 topic bw10 ros2 topic find11 Clean upSummaryNext stepsBackgroundROS 2 breaks complex systems down into many modular nodes. +Topics are a vital element of the ROS graph that act as a bus for nodes to exchange messages.A node may publish data to any number of topics and simultaneously have subscriptions to any number of topics.Topics are one of the main ways in which data is moved between nodes and therefore between different parts of the system.PrerequisitesTheprevious tutorialprovides some useful background information on nodes that is built upon here.As always, don’t forget to source ROS 2 inevery new terminal you open.Tasks1 SetupBy now you should be comfortable starting up turtlesim.Open a new terminal and run:ros2 run turtlesim turtlesim_nodeOpen another terminal and run:ros2 run turtlesim turtle_teleop_keyRecall from theprevious tutorialthat the names of these nodes are/turtlesimand/teleop_turtleby default.2 rqt_graphThroughout this tutorial, we will userqt_graphto visualize the changing nodes and topics, as well as the connections between them.Theturtlesim tutorialtells you how to install rqt and all its plugins, includingrqt_graph.To run rqt_graph, open a new terminal and enter the command:rqt_graphYou can also open rqt_graph by openingrqtand selectingPlugins>Introspection>Node Graph.You should see the above nodes and topic, as well as two actions around the periphery of the graph (let’s ignore those for now). +If you hover your mouse over the topic in the center, you’ll see the color highlighting like in the image above.The graph is depicting how the/turtlesimnode and the/teleop_turtlenode are communicating with each other over a topic. +The/teleop_turtlenode is publishing data (the keystrokes you enter to move the turtle around) to the/turtle1/cmd_veltopic, and the/turtlesimnode is subscribed to that topic to receive the data.The highlighting feature of rqt_graph is very helpful when examining more complex systems with many nodes and topics connected in many different ways.rqt_graph is a graphical introspection tool. +Now we’ll look at some command line tools for introspecting topics.3 ros2 topic listRunning theros2topiclistcommand in a new terminal will return a list of all the topics currently active in the system:/parameter_events/rosout/turtle1/cmd_vel/turtle1/color_sensor/turtle1/poseros2topiclist-twill return the same list of topics, this time with the topic type appended in brackets:/parameter_events [rcl_interfaces/msg/ParameterEvent]/rosout [rcl_interfaces/msg/Log]/turtle1/cmd_vel [geometry_msgs/msg/Twist]/turtle1/color_sensor [turtlesim/msg/Color]/turtle1/pose [turtlesim/msg/Pose]These attributes, particularly the type, are how nodes know they’re talking about the same information as it moves over topics.If you’re wondering where all these topics are in rqt_graph, you can uncheck all the boxes underHide:For now, though, leave those options checked to avoid confusion.4 ros2 topic echoTo see the data being published on a topic, use:ros2 topic echo Since we know that/teleop_turtlepublishes data to/turtlesimover the/turtle1/cmd_veltopic, let’s useechoto introspect that topic:ros2 topic echo /turtle1/cmd_velAt first, this command won’t return any data. +That’s because it’s waiting for/teleop_turtleto publish something.Return to the terminal whereturtle_teleop_keyis running and use the arrows to move the turtle around. +Watch the terminal where yourechois running at the same time, and you’ll see position data being published for every movement you make:linear:x: 2.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.0---Now return to rqt_graph and uncheck theDebugbox./_ros2cli_26646is the node created by theechocommand we just ran (the number might be different). +Now you can see that the publisher is publishing data over thecmd_veltopic, and two subscribers are subscribed to it.5 ros2 topic infoTopics don’t have to only be one-to-one communication; they can be one-to-many, many-to-one, or many-to-many.Another way to look at this is running:ros2 topic info /turtle1/cmd_velWhich will return:Type: geometry_msgs/msg/TwistPublisher count: 1Subscription count: 26 ros2 interface showNodes send data over topics using messages. +Publishers and subscribers must send and receive the same type of message to communicate.The topic types we saw earlier after runningros2topiclist-tlet us know what message type is used on each topic. +Recall that thecmd_veltopic has the type:geometry_msgs/msg/TwistThis means that in the packagegeometry_msgsthere is amsgcalledTwist.Now we can runros2interfaceshowon this type to learn its details. +Specifically, what structure of data the message expects.ros2 interface show geometry_msgs/msg/TwistFor the message type from above it yields:#Thisexpressesvelocityinfreespacebrokenintoitslinearandangularparts.Vector3 linearfloat64 xfloat64 yfloat64 zVector3 angularfloat64 xfloat64 yfloat64 zThis tells you that the/turtlesimnode is expecting a message with two vectors,linearandangular, of three elements each. +If you recall the data we saw/teleop_turtlepassing to/turtlesimwith theechocommand, it’s in the same structure:linear:x: 2.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.0---7 ros2 topic pubNow that you have the message structure, you can publish data to a topic directly from the command line using:ros2 topic pub ''The''argument is the actual data you’ll pass to the topic, in the structure you just discovered in the previous section.The turtle (and commonly the real robots which it is meant to emulate) require a steady stream of commands to operate continuously. +So, to get the turtle moving, and keep it moving, you can use the following command. +It’s important to note that this argument needs to be input in YAML syntax. +Input the full command like so:ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"With no command-line options,ros2topicpubpublishes the command in a steady stream at 1 Hz.At times you may want to publish data to your topic only once (rather than continuously). +To publish your command just once add the--onceoption.ros2 topic pub --once -w 2 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"--onceis an optional argument meaning “publish one message then exit”.-w2is an optional argument meaning “wait for two matching subscriptions”. +This is needed because we have both turtlesim and the topic echo subscribed.You will see the following output in the terminal:Waiting for at least 2 matching subscription(s)...publisher: beginning looppublishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8))And you will see your turtle move like so:You can refresh rqt_graph to see what’s happening graphically. +You will see that theros2topicpub...node (/_ros2cli_30358) is publishing over the/turtle1/cmd_veltopic, which is being received by both theros2topicecho...node (/_ros2cli_26646) and the/turtlesimnode now.Finally, you can runechoon theposetopic and recheck rqt_graph:ros2 topic echo /turtle1/poseYou can see that the/turtlesimnode is also publishing to theposetopic, which the newechonode has subscribed to.When publishing messages with timestamps,pubhas two methods to automatically fill them out with the current time. +For messages with astd_msgs/msg/Header, the header field can be set toautoto fill out thestampfield.ros2 topic pub /pose geometry_msgs/msg/PoseStamped '{header: "auto", pose: {position: {x: 1.0, y: 2.0, z: 3.0}}}'If the message does not use a full header, but just has a field with typebuiltin_interfaces/msg/Time, that can be set to the valuenow.ros2 topic pub /reference sensor_msgs/msg/TimeReference '{header: "auto", time_ref: "now", source: "dumy"}'8 ros2 topic hzYou can also view the rate at which data is published using:ros2 topic hz /turtle1/poseIt will return data on the rate at which the/turtlesimnode is publishing data to theposetopic.average rate: 59.354min: 0.005s max: 0.027s std dev: 0.00284s window: 58Recall that you set the rate ofturtle1/cmd_velto publish at a steady 1 Hz usingros2topicpub--rate1. +If you run the above command withturtle1/cmd_velinstead ofturtle1/pose, you will see an average reflecting that rate.9 ros2 topic bwThe bandwidth used by a topic can be viewed using:ros2 topic bw /turtle1/poseIt returns the bandwidth utilization and number of messages being published to the/turtle1/posetopic.Subscribed to [/turtle1/pose]1.51 KB/s from 62 messagesMessage size mean: 0.02 KB min: 0.02 KB max: 0.02 KB10 ros2 topic findTo list a list of available topics of a given type use:ros2 topic find Recall that thecmd_veltopic has the type:geometry_msgs/msg/TwistUsing thefindcommand outputs topics available when given the message type:ros2 topic find geometry_msgs/msg/TwistThis outputs:/turtle1/cmd_vel11 Clean upAt this point you’ll have a lot of nodes running. +Don’t forget to stop them by enteringCtrl+Cin each terminal.SummaryNodes publish information over topics, which allows any number of other nodes to subscribe to and access that information. +In this tutorial you examined the connections between several nodes over topics using rqt_graph and command line tools. +You should now have a good idea of how data moves around a ROS 2 system.Next stepsNext you’ll learn about another communication type in the ROS graph with the tutorialUnderstanding services. + +Code Examples: + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +rqt_graph + +Language: unknown +/parameter_events/rosout/turtle1/cmd_vel/turtle1/color_sensor/turtle1/pose + +Language: unknown +/parameter_events [rcl_interfaces/msg/ParameterEvent]/rosout [rcl_interfaces/msg/Log]/turtle1/cmd_vel [geometry_msgs/msg/Twist]/turtle1/color_sensor [turtlesim/msg/Color]/turtle1/pose [turtlesim/msg/Pose] + +Language: unknown +ros2 topic echo + +Language: unknown +ros2 topic echo /turtle1/cmd_vel + +Language: unknown +linear:x: 2.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.0--- + +Language: unknown +ros2 topic info /turtle1/cmd_vel + +Language: unknown +Type: geometry_msgs/msg/TwistPublisher count: 1Subscription count: 2 + +Language: unknown +geometry_msgs/msg/Twist + +Language: unknown +ros2 interface show geometry_msgs/msg/Twist + +Language: unknown +#Thisexpressesvelocityinfreespacebrokenintoitslinearandangularparts.Vector3 linearfloat64 xfloat64 yfloat64 zVector3 angularfloat64 xfloat64 yfloat64 z + +Language: unknown +linear:x: 2.0y: 0.0z: 0.0angular:x: 0.0y: 0.0z: 0.0--- + +Language: unknown +ros2 topic pub '' + +Language: unknown +ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}" + +Language: unknown +ros2 topic pub --once -w 2 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}" + +Language: unknown +Waiting for at least 2 matching subscription(s)...publisher: beginning looppublishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=2.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=1.8)) + +Language: unknown +ros2 topic echo /turtle1/pose + +Language: unknown +ros2 topic pub /pose geometry_msgs/msg/PoseStamped '{header: "auto", pose: {position: {x: 1.0, y: 2.0, z: 3.0}}}' + +Language: unknown +ros2 topic pub /reference sensor_msgs/msg/TimeReference '{header: "auto", time_ref: "now", source: "dumy"}' + +Language: unknown +ros2 topic hz /turtle1/pose + +Language: unknown +average rate: 59.354min: 0.005s max: 0.027s std dev: 0.00284s window: 58 + +Language: unknown +ros2 topic bw /turtle1/pose + +Language: unknown +Subscribed to [/turtle1/pose]1.51 KB/s from 62 messagesMessage size mean: 0.02 KB min: 0.02 KB max: 0.02 KB + +Language: unknown +ros2 topic find + +Language: unknown +geometry_msgs/msg/Twist + +Language: unknown +ros2 topic find geometry_msgs/msg/Twist + +Language: unknown +/turtle1/cmd_vel diff --git "a/exported_docs/ros2/Unlocking_the_potential_of_Fast_DDS_middleware_[community-contributed]\357\203\201.txt" "b/exported_docs/ros2/Unlocking_the_potential_of_Fast_DDS_middleware_[community-contributed]\357\203\201.txt" new file mode 100644 index 0000000..6f620c6 --- /dev/null +++ "b/exported_docs/ros2/Unlocking_the_potential_of_Fast_DDS_middleware_[community-contributed]\357\203\201.txt" @@ -0,0 +1,168 @@ +Title: Unlocking the potential of Fast DDS middleware [community-contributed] +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/FastDDS-Configuration.html +Section: Installation +-------------------------------------------------------------------------------- + +Unlocking the potential of Fast DDS middleware [community-contributed]Goal:This tutorial will show how to use the extended configuration capabilities of Fast DDS in ROS 2.Tutorial level:AdvancedTime:20 minutesTable of ContentsBackgroundPrerequisitesMixing synchronous and asynchronous publications in the same nodeCreate the node with the publishersCreate the XML file with the profile configurationExecute the publisher nodeCreate a node with the subscribersExecute the subscriber nodeAnalysis of the exampleUsing other FastDDS capabilities with XMLLimiting the number of matching subscribersUsing partitions within the topicConfiguring a service and a clientCreate the nodes with the service and clientCreate the XML profiles for the service and clientExecute the nodesBackgroundThe interface between the ROS 2 stack andFast DDSis provided by the ROS 2 middleware implementationrmw_fastrtps. +This implementation is available in all ROS 2 distributions, both from binaries and from sources.ROS 2 RMW only allows for the configuration of certain middleware QoS +(seeROS 2 QoS policies). +However,rmw_fastrtpsoffers extended configuration capabilities to take full advantage of the features inFast DDS. +This tutorial will guide you through a series of examples explaining how to use XML files to unlock this extended configuration.In order to get more information about usingFast DDSon ROS 2, please check thefollowing documentation.PrerequisitesThis tutorial assumes that you know how tocreate a package. +It also assumes you know how to write asimple publisher and subscriberand asimple service and client. +Although the examples are implemented in C++, the same concepts apply to Python packages.Mixing synchronous and asynchronous publications in the same nodeIn this first example, a node with two publishers, one of them with synchronous publication mode and the other one with asynchronous publication mode, will be created.rmw_fastrtpsuses synchronous publication mode by default.With synchronous publication mode the data is sent directly within the context of the user thread. +This entails that any blocking call occurring during the write operation would block the user thread, thus preventing the application from continuing its operation. +However, this mode typically yields higher throughput rates at lower latencies, since there is no notification nor context switching between threads.On the other hand, with asynchronous publication mode, each time the publisher invokes the write operation, the data is copied into a queue, +a background thread (asynchronous thread) is notified about the addition to the queue, and control of the thread is returned to the user before the data is actually sent. +The background thread is in charge of consuming the queue and sending the data to every matched reader.Create the node with the publishersFirst, create a new package namedsync_async_node_example_cppon a new workspace:LinuxmacOSWindowsmkdir -p ~/ros2_ws/srccd ~/ros2_ws/srcros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cppmkdir -p ~/ros2_ws/srccd ~/ros2_ws/srcros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cppmd \ros2_ws\srccd \ros2_ws\srcros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cppThen, add a file namedsrc/sync_async_writer.cppto the package, with the following content. +Note that the synchronous publisher will be publishing on topicsync_topic, while the asynchronous one will be publishing on topicasync_topic.#include#include#include#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;classSyncAsyncPublisher:publicrclcpp::Node{public:SyncAsyncPublisher():Node("sync_async_publisher"),count_(0){// Create the synchronous publisher on topic 'sync_topic'sync_publisher_=this->create_publisher("sync_topic",10);// Create the asynchronous publisher on topic 'async_topic'async_publisher_=this->create_publisher("async_topic",10);// Actions to run every time the timer expiresautotimer_callback=[this](){// Create a new message to be sentautosync_message=std_msgs::msg::String();sync_message.data="SYNC: Hello, world! "+std::to_string(count_);// Log the message to the console to show progressRCLCPP_INFO(this->get_logger(),"Synchronously publishing: '%s'",sync_message.data.c_str());// Publish the message using the synchronous publishersync_publisher_->publish(sync_message);// Create a new message to be sentautoasync_message=std_msgs::msg::String();async_message.data="ASYNC: Hello, world! "+std::to_string(count_);// Log the message to the console to show progressRCLCPP_INFO(this->get_logger(),"Asynchronously publishing: '%s'",async_message.data.c_str());// Publish the message using the asynchronous publisherasync_publisher_->publish(async_message);// Prepare the count for the next messagecount_++;};// This timer will trigger the publication of new data every half a secondtimer_=this->create_wall_timer(500ms,timer_callback);}private:// This timer will trigger the publication of new data every half a secondrclcpp::TimerBase::SharedPtrtimer_;// A publisher that publishes asynchronouslyrclcpp::Publisher::SharedPtrasync_publisher_;// A publisher that publishes synchronouslyrclcpp::Publisher::SharedPtrsync_publisher_;// Number of messages sent so farsize_tcount_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}Now open theCMakeLists.txtfile and add a new executable and name itSyncAsyncWriterso you can run your node usingros2run:add_executable(SyncAsyncWritersrc/sync_async_writer.cpp)ament_target_dependencies(SyncAsyncWriterrclcppstd_msgs)Finally, add theinstall(TARGETS…)section soros2runcan find your executable:install(TARGETSSyncAsyncWriterDESTINATIONlib/${PROJECT_NAME})You can clean up yourCMakeLists.txtby removing some unnecessary sections and comments, so it looks like this:cmake_minimum_required(VERSION3.8)project(sync_async_node_example_cpp)# Default to C++14if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD14)endif()if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()find_package(ament_cmakeREQUIRED)find_package(rclcppREQUIRED)find_package(std_msgsREQUIRED)add_executable(SyncAsyncWritersrc/sync_async_writer.cpp)ament_target_dependencies(SyncAsyncWriterrclcppstd_msgs)install(TARGETSSyncAsyncWriterDESTINATIONlib/${PROJECT_NAME})ament_package()If this node is built and run now, both publishers will behave the same, publishing asynchronously in both topics, because this is the default publication mode. +The default publication mode configuration can be changed in runtime during the node launching, using an XML file.Create the XML file with the profile configurationCreate a file with nameSyncAsync.xmland the following content:DYNAMICDYNAMICDYNAMICSYNCHRONOUSDYNAMICASYNCHRONOUSNote that several profiles for publisher and subscriber are defined. +Two default profiles which are defined setting theis_default_profiletotrue, and two profiles with names that coincide with those of the previously defined topics:sync_topicand another one forasync_topic. +These last two profiles set the publication mode toSYNCHRONOUSorASYNCHRONOUSaccordingly. +Note also that all profiles specify ahistoryMemoryPolicyvalue, which is needed for the example to work, and the reason will be explained later on this tutorial.Execute the publisher nodeYou will need to export the following environment variables for the XML to be loaded:LinuxmacOSWindowsexport RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xmlexport RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xmlSET RMW_IMPLEMENTATION=rmw_fastrtps_cppSET RMW_FASTRTPS_USE_QOS_FROM_XML=1SET FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xmlFinally, ensure you have sourced your setup files and run the node:source install/setup.bashros2 run sync_async_node_example_cpp SyncAsyncWriterYou should see the publishers sending the data from the publishing node, like so:[INFO] [1612972049.994630332] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 0'[INFO] [1612972049.995097767] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 0'[INFO] [1612972050.494478706] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 1'[INFO] [1612972050.494664334] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 1'[INFO] [1612972050.994368474] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 2'[INFO] [1612972050.994549851] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 2'Now you have a synchronous publisher and an asynchronous publisher running inside the same node.Create a node with the subscribersNext, a new node with the subscribers that will listen to thesync_topicandasync_topicpublications is going to be created. +In a new source file namedsrc/sync_async_reader.cppwrite the following content:#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"classSyncAsyncSubscriber:publicrclcpp::Node{public:SyncAsyncSubscriber():Node("sync_async_subscriber"){// Lambda function to run every time a new message is receivedautotopic_callback=[this](conststd_msgs::msg::String&msg){RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg.data.c_str());};// Create the synchronous subscriber on topic 'sync_topic'// and tie it to the topic_callbacksync_subscription_=this->create_subscription("sync_topic",10,topic_callback);// Create the asynchronous subscriber on topic 'async_topic'// and tie it to the topic_callbackasync_subscription_=this->create_subscription("async_topic",10,topic_callback);}private:// A subscriber that listens to topic 'sync_topic'rclcpp::Subscription::SharedPtrsync_subscription_;// A subscriber that listens to topic 'async_topic'rclcpp::Subscription::SharedPtrasync_subscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}Open theCMakeLists.txtfile and add a new executable and name itSyncAsyncReaderunder the previousSyncAsyncWriter:add_executable(SyncAsyncReadersrc/sync_async_reader.cpp)ament_target_dependencies(SyncAsyncReaderrclcppstd_msgs)install(TARGETSSyncAsyncReaderDESTINATIONlib/${PROJECT_NAME})Execute the subscriber nodeWith the publisher node running in one terminal, open another one and export the required environment variables for the XML to be loaded:LinuxmacOSWindowsexport RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xmlexport RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xmlSET RMW_IMPLEMENTATION=rmw_fastrtps_cppSET RMW_FASTRTPS_USE_QOS_FROM_XML=1SET FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xmlFinally, ensure you have sourced your setup files and run the node:source install/setup.bashros2 run sync_async_node_example_cpp SyncAsyncReaderYou should see the subscribers receiving the data from the publishing node, like so:[INFO] [1612972054.495429090] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 10'[INFO] [1612972054.995410057] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 10'[INFO] [1612972055.495453494] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 11'[INFO] [1612972055.995396561] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 11'[INFO] [1612972056.495534818] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 12'[INFO] [1612972056.995473953] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 12'Analysis of the exampleConfiguration profiles XMLThe XML file defines several configurations for publishers and subscribers. +You can have a default publisher configuration profile and several topic-specific publisher profiles. +The only requirement is that all publisher profiles have a different name and that there is only a single default profile. +The same goes for subscribers.In order to define a configuration for a specific topic, just name the profile after the the ROS 2 topic name (like/sync_topicand/async_topicin the example), +andrmw_fastrtpswill apply this profile to all publishers and subscribers for that topic. +The default configuration profile is identified by the attributeis_default_profileset totrue, and acts as a fallback profile when there is no other one with a name matching the topic name.The environment variableFASTRTPS_DEFAULT_PROFILES_FILEis used to informFast DDSthe path to the XML file with the configuration profiles to load.RMW_FASTRTPS_USE_QOS_FROM_XMLAmong all the configurable attributes,rmw_fastrtpstreatspublishModeandhistoryMemoryPolicydifferently. +By default, these values are set toASYNCHRONOUSandPREALLOCATED_WITH_REALLOCwithin thermw_fastrtpsimplementation, and the values set on the XML file are ignored. +In order to use the values in the XML file, the environment variableRMW_FASTRTPS_USE_QOS_FROM_XMLmust be set to1.However, this entailsanother caveat: IfRMW_FASTRTPS_USE_QOS_FROM_XMLis set, but the XML file does not definepublishModeorhistoryMemoryPolicy, these attributes take theFast DDSdefault value instead of thermw_fastrtpsdefault value. +This is important, especially forhistoryMemoryPolicy, because theFast DDSdeafult value isPREALLOCATEDwhich does not work with ROS2 topic data types. +Therefore, in the example, a valid value for this policy has been explicitly set (DYNAMIC).Prioritization of rmw_qos_profile_tROS 2 QoS contained inrmw_qos_profile_tare always honored, unless set to*_SYSTEM_DEFAULT. +In that case, XML values (orFast DDSdefault values in the absence of XML ones) are applied. +This means that if any QoS inrmw_qos_profile_tis set to something other than*_SYSTEM_DEFAULT, the corresponding value in the XML is ignored.Using other FastDDS capabilities with XMLAlthough we have created a node with two publishers with different configuration, it is not easy to check that they are behaving differently. +Now that the basics of XML profiles have been covered, let us use them to configure something which has some visual effect on the nodes. +Specifically, a maximum number of matching subscribers on one of the publishers and a partition definition on the other will be set. +Note that these are only very simple examples among all the configuration attributes that can be tuned onrmw_fastrtpsthrough XML files. +Please refer to*Fast DDS* documentationto see the whole list of attributes that can be configured through XML files.Limiting the number of matching subscribersAdd a maximum number of matched subscribers to the/async_topicpublisher profile. +It should look like this:DYNAMICASYNCHRONOUS011The number of matching subscribers is being limited to one.Now open three terminals and do not forget to source the setup files and to set the required environment variables. +On the first terminal run the publisher node, and the subscriber node on the other two. +You should see that only the first subscriber node receives the messages from both topics. +The second one could not complete the matching process in the/async_topicbecause the publisher prevented it, as it had already reached its maximum of matched publishers. +Consequently, only the messages from the/sync_topicare going to be received in this third terminal:[INFO] [1613127657.088860890] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 18'[INFO] [1613127657.588896594] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 19'[INFO] [1613127658.088849401] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 20'Using partitions within the topicThe partitions feature can be used to control which publishers and subscribers exchange information within the same topic.Partitions introduce a logical entity isolation level concept inside the physical isolation induced by a Domain ID. +For a publisher to communicate with a subscriber, they have to belong at least to one common partition. +Partitions represent another level to separate publishers and subscribers beyond domain and topic. +Unlike domain and topic, an endpoint can belong to several partitions at the same time. +For certain data to be shared over different domains or topics, there must be a different publisher for each, sharing its own history of changes. +However, a single publisher can share the same data sample over different partitions using a single topic data change, thus reducing network overload.Let us change the/sync_topicpublisher to partitionpart1and create a new/sync_topicsubscriber which uses partitionpart2. +Their profiles should now look like this:DYNAMICSYNCHRONOUSpart1DYNAMICpart2Open two terminals. +Do not forget to source the setup files and to set the required environment variables. +On the first terminal run the publisher node, and the subscriber node on the other one. +You should see that only the/async_topicmessages are reaching the subscriber. +The/sync_topicsubscriber is not receiving the data as it is in a different partition from the corresponding publisher.[INFO] [1612972054.995410057] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 10'[INFO] [1612972055.995396561] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 11'[INFO] [1612972056.995473953] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 12'Configuring a service and a clientServices and clients have a publisher and a subscriber each, that communicate through two different topics. +For example, for a service namedpingthere is:A service subscriber listening to requests on/rq/ping.A service publisher sending responses on/rr/ping.A client publisher sending requests on/rq/ping.A client subscriber listening to responses on/rr/ping.Although you can use these topic names to set the configuration profiles on the XML, sometimes you may wish to apply the same profile to all services or clients on a node. +Instead of copying the same profile with all topic names generated for all services, you can just create a publisher and subscriber profile pair namedservice. +The same can be done for clients creating a pair namedclient.Create the nodes with the service and clientStart creating the node with the service. +Add a new source file namedsrc/ping_service.cppon your package with the following content:#include#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/trigger.hpp"/*** Service action: responds with success=true and prints the request on the console*/voidping(conststd::shared_ptrrequest,std::shared_ptrresponse){// The request data is unused(void)request;// Build the responseresponse->success=true;// Log to the consoleRCLCPP_INFO(rclcpp::get_logger("ping_server"),"Incoming request");RCLCPP_INFO(rclcpp::get_logger("ping_server"),"Sending back response");}intmain(intargc,char**argv){rclcpp::init(argc,argv);// Create the node and the servicestd::shared_ptrnode=rclcpp::Node::make_shared("ping_server");rclcpp::Service::SharedPtrservice=node->create_service("ping",&ping);// Log that the service is readyRCLCPP_INFO(rclcpp::get_logger("ping_server"),"Ready to serve.");// run the noderclcpp::spin(node);rclcpp::shutdown();}Create the client in a file namedsrc/ping_client.cppwith the following content:#include#include#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/trigger.hpp"usingnamespacestd::chrono_literals;intmain(intargc,char**argv){rclcpp::init(argc,argv);// Create the node and the clientstd::shared_ptrnode=rclcpp::Node::make_shared("ping_client");rclcpp::Client::SharedPtrclient=node->create_client("ping");// Create a requestautorequest=std::make_shared();// Wait for the service to be availablewhile(!client->wait_for_service(1s)){if(!rclcpp::ok()){RCLCPP_ERROR(rclcpp::get_logger("ping_client"),"Interrupted while waiting for the service. Exiting.");return0;}RCLCPP_INFO(rclcpp::get_logger("ping_client"),"Service not available, waiting again...");}// Now that the service is available, send the requestRCLCPP_INFO(rclcpp::get_logger("ping_client"),"Sending request");autoresult=client->async_send_request(request);// Wait for the result and log it to the consoleif(rclcpp::spin_until_future_complete(node,result)==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(rclcpp::get_logger("ping_client"),"Response received");}else{RCLCPP_ERROR(rclcpp::get_logger("ping_client"),"Failed to call service ping");}rclcpp::shutdown();return0;}Open theCMakeLists.txtfile and add two new executablesping_serviceandping_client:find_package(example_interfacesREQUIRED)add_executable(ping_servicesrc/ping_service.cpp)ament_target_dependencies(ping_serviceexample_interfacesrclcpp)add_executable(ping_clientsrc/ping_client.cpp)ament_target_dependencies(ping_clientexample_interfacesrclcpp)install(TARGETSping_serviceDESTINATIONlib/${PROJECT_NAME})install(TARGETSping_clientDESTINATIONlib/${PROJECT_NAME})Finally, build the package.Create the XML profiles for the service and clientCreate a file with nameping.xmlwith the following content:DYNAMICDYNAMICDYNAMICSYNCHRONOUSDYNAMICASYNCHRONOUSThis configuration file sets the publication mode toSYNCHRONOUSon the service and toASYNCHRONOUSon the client. +Note that we are only defining the publisher profiles for both the service and the client, but subscriber profiles could be provided too.Execute the nodesOpen two terminals and source the setup files on each one. +Then set the required environment variables for the XML to be loaded:LinuxmacOSWindowsexport RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/ping.xmlexport RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/ping.xmlSET RMW_IMPLEMENTATION=rmw_fastrtps_cppSET RMW_FASTRTPS_USE_QOS_FROM_XML=1SET FASTRTPS_DEFAULT_PROFILES_FILE=path/to/ping.xmlOn the first terminal run the service node.ros2 run sync_async_node_example_cpp ping_serviceYou should see the service waiting for requests:[INFO] [1612977403.805799037] [ping_server]: Ready to serve.On the second terminal, run the client node.ros2 run sync_async_node_example_cpp ping_clientYou should see the client sending the request and receiving the response:[INFO] [1612977404.805799037] [ping_client]: Sending request[INFO] [1612977404.825473835] [ping_client]: Response receivedAt the same time, the output in the server console has been updated:[INFO] [1612977403.805799037] [ping_server]: Ready to serve.[INFO] [1612977404.807314904] [ping_server]: Incoming request[INFO] [1612977404.836405125] [ping_server]: Sending back response + +Code Examples: + +Language: unknown +mkdir -p ~/ros2_ws/srccd ~/ros2_ws/srcros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cpp + +Language: unknown +mkdir -p ~/ros2_ws/srccd ~/ros2_ws/srcros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cpp + +Language: unknown +md \ros2_ws\srccd \ros2_ws\srcros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies rclcpp std_msgs -- sync_async_node_example_cpp + +Language: unknown +#include#include#include#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;classSyncAsyncPublisher:publicrclcpp::Node{public:SyncAsyncPublisher():Node("sync_async_publisher"),count_(0){// Create the synchronous publisher on topic 'sync_topic'sync_publisher_=this->create_publisher("sync_topic",10);// Create the asynchronous publisher on topic 'async_topic'async_publisher_=this->create_publisher("async_topic",10);// Actions to run every time the timer expiresautotimer_callback=[this](){// Create a new message to be sentautosync_message=std_msgs::msg::String();sync_message.data="SYNC: Hello, world! "+std::to_string(count_);// Log the message to the console to show progressRCLCPP_INFO(this->get_logger(),"Synchronously publishing: '%s'",sync_message.data.c_str());// Publish the message using the synchronous publishersync_publisher_->publish(sync_message);// Create a new message to be sentautoasync_message=std_msgs::msg::String();async_message.data="ASYNC: Hello, world! "+std::to_string(count_);// Log the message to the console to show progressRCLCPP_INFO(this->get_logger(),"Asynchronously publishing: '%s'",async_message.data.c_str());// Publish the message using the asynchronous publisherasync_publisher_->publish(async_message);// Prepare the count for the next messagecount_++;};// This timer will trigger the publication of new data every half a secondtimer_=this->create_wall_timer(500ms,timer_callback);}private:// This timer will trigger the publication of new data every half a secondrclcpp::TimerBase::SharedPtrtimer_;// A publisher that publishes asynchronouslyrclcpp::Publisher::SharedPtrasync_publisher_;// A publisher that publishes synchronouslyrclcpp::Publisher::SharedPtrsync_publisher_;// Number of messages sent so farsize_tcount_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +add_executable(SyncAsyncWritersrc/sync_async_writer.cpp)ament_target_dependencies(SyncAsyncWriterrclcppstd_msgs) + +Language: unknown +install(TARGETSSyncAsyncWriterDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +cmake_minimum_required(VERSION3.8)project(sync_async_node_example_cpp)# Default to C++14if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD14)endif()if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()find_package(ament_cmakeREQUIRED)find_package(rclcppREQUIRED)find_package(std_msgsREQUIRED)add_executable(SyncAsyncWritersrc/sync_async_writer.cpp)ament_target_dependencies(SyncAsyncWriterrclcppstd_msgs)install(TARGETSSyncAsyncWriterDESTINATIONlib/${PROJECT_NAME})ament_package() + +Language: unknown +DYNAMICDYNAMICDYNAMICSYNCHRONOUSDYNAMICASYNCHRONOUS + +Language: unknown +export RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xml + +Language: unknown +export RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xml + +Language: unknown +SET RMW_IMPLEMENTATION=rmw_fastrtps_cppSET RMW_FASTRTPS_USE_QOS_FROM_XML=1SET FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xml + +Language: unknown +source install/setup.bashros2 run sync_async_node_example_cpp SyncAsyncWriter + +Language: unknown +[INFO] [1612972049.994630332] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 0'[INFO] [1612972049.995097767] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 0'[INFO] [1612972050.494478706] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 1'[INFO] [1612972050.494664334] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 1'[INFO] [1612972050.994368474] [sync_async_publisher]: Synchronously publishing: 'SYNC: Hello, world! 2'[INFO] [1612972050.994549851] [sync_async_publisher]: Asynchronously publishing: 'ASYNC: Hello, world! 2' + +Language: unknown +#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"classSyncAsyncSubscriber:publicrclcpp::Node{public:SyncAsyncSubscriber():Node("sync_async_subscriber"){// Lambda function to run every time a new message is receivedautotopic_callback=[this](conststd_msgs::msg::String&msg){RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg.data.c_str());};// Create the synchronous subscriber on topic 'sync_topic'// and tie it to the topic_callbacksync_subscription_=this->create_subscription("sync_topic",10,topic_callback);// Create the asynchronous subscriber on topic 'async_topic'// and tie it to the topic_callbackasync_subscription_=this->create_subscription("async_topic",10,topic_callback);}private:// A subscriber that listens to topic 'sync_topic'rclcpp::Subscription::SharedPtrsync_subscription_;// A subscriber that listens to topic 'async_topic'rclcpp::Subscription::SharedPtrasync_subscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +add_executable(SyncAsyncReadersrc/sync_async_reader.cpp)ament_target_dependencies(SyncAsyncReaderrclcppstd_msgs)install(TARGETSSyncAsyncReaderDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +export RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xml + +Language: unknown +export RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xml + +Language: unknown +SET RMW_IMPLEMENTATION=rmw_fastrtps_cppSET RMW_FASTRTPS_USE_QOS_FROM_XML=1SET FASTRTPS_DEFAULT_PROFILES_FILE=path/to/SyncAsync.xml + +Language: unknown +source install/setup.bashros2 run sync_async_node_example_cpp SyncAsyncReader + +Language: unknown +[INFO] [1612972054.495429090] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 10'[INFO] [1612972054.995410057] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 10'[INFO] [1612972055.495453494] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 11'[INFO] [1612972055.995396561] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 11'[INFO] [1612972056.495534818] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 12'[INFO] [1612972056.995473953] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 12' + +Language: unknown +DYNAMICASYNCHRONOUS011 + +Language: unknown +[INFO] [1613127657.088860890] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 18'[INFO] [1613127657.588896594] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 19'[INFO] [1613127658.088849401] [sync_async_subscriber]: I heard: 'SYNC: Hello, world! 20' + +Language: unknown +DYNAMICSYNCHRONOUSpart1DYNAMICpart2 + +Language: unknown +[INFO] [1612972054.995410057] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 10'[INFO] [1612972055.995396561] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 11'[INFO] [1612972056.995473953] [sync_async_subscriber]: I heard: 'ASYNC: Hello, world! 12' + +Language: unknown +#include#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/trigger.hpp"/*** Service action: responds with success=true and prints the request on the console*/voidping(conststd::shared_ptrrequest,std::shared_ptrresponse){// The request data is unused(void)request;// Build the responseresponse->success=true;// Log to the consoleRCLCPP_INFO(rclcpp::get_logger("ping_server"),"Incoming request");RCLCPP_INFO(rclcpp::get_logger("ping_server"),"Sending back response");}intmain(intargc,char**argv){rclcpp::init(argc,argv);// Create the node and the servicestd::shared_ptrnode=rclcpp::Node::make_shared("ping_server");rclcpp::Service::SharedPtrservice=node->create_service("ping",&ping);// Log that the service is readyRCLCPP_INFO(rclcpp::get_logger("ping_server"),"Ready to serve.");// run the noderclcpp::spin(node);rclcpp::shutdown();} + +Language: unknown +#include#include#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/trigger.hpp"usingnamespacestd::chrono_literals;intmain(intargc,char**argv){rclcpp::init(argc,argv);// Create the node and the clientstd::shared_ptrnode=rclcpp::Node::make_shared("ping_client");rclcpp::Client::SharedPtrclient=node->create_client("ping");// Create a requestautorequest=std::make_shared();// Wait for the service to be availablewhile(!client->wait_for_service(1s)){if(!rclcpp::ok()){RCLCPP_ERROR(rclcpp::get_logger("ping_client"),"Interrupted while waiting for the service. Exiting.");return0;}RCLCPP_INFO(rclcpp::get_logger("ping_client"),"Service not available, waiting again...");}// Now that the service is available, send the requestRCLCPP_INFO(rclcpp::get_logger("ping_client"),"Sending request");autoresult=client->async_send_request(request);// Wait for the result and log it to the consoleif(rclcpp::spin_until_future_complete(node,result)==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(rclcpp::get_logger("ping_client"),"Response received");}else{RCLCPP_ERROR(rclcpp::get_logger("ping_client"),"Failed to call service ping");}rclcpp::shutdown();return0;} + +Language: unknown +find_package(example_interfacesREQUIRED)add_executable(ping_servicesrc/ping_service.cpp)ament_target_dependencies(ping_serviceexample_interfacesrclcpp)add_executable(ping_clientsrc/ping_client.cpp)ament_target_dependencies(ping_clientexample_interfacesrclcpp)install(TARGETSping_serviceDESTINATIONlib/${PROJECT_NAME})install(TARGETSping_clientDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +DYNAMICDYNAMICDYNAMICSYNCHRONOUSDYNAMICASYNCHRONOUS + +Language: unknown +export RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/ping.xml + +Language: unknown +export RMW_IMPLEMENTATION=rmw_fastrtps_cppexport RMW_FASTRTPS_USE_QOS_FROM_XML=1export FASTRTPS_DEFAULT_PROFILES_FILE=path/to/ping.xml + +Language: unknown +SET RMW_IMPLEMENTATION=rmw_fastrtps_cppSET RMW_FASTRTPS_USE_QOS_FROM_XML=1SET FASTRTPS_DEFAULT_PROFILES_FILE=path/to/ping.xml + +Language: unknown +ros2 run sync_async_node_example_cpp ping_service + +Language: unknown +[INFO] [1612977403.805799037] [ping_server]: Ready to serve. + +Language: unknown +ros2 run sync_async_node_example_cpp ping_client + +Language: unknown +[INFO] [1612977404.805799037] [ping_client]: Sending request[INFO] [1612977404.825473835] [ping_client]: Response received + +Language: unknown +[INFO] [1612977403.805799037] [ping_server]: Ready to serve.[INFO] [1612977404.807314904] [ping_server]: Incoming request[INFO] [1612977404.836405125] [ping_server]: Sending back response diff --git "a/exported_docs/ros2/Using_Fast_DDS_Discovery_Server_as_discovery_protocol_[community-contributed]\357\203\201.txt" "b/exported_docs/ros2/Using_Fast_DDS_Discovery_Server_as_discovery_protocol_[community-contributed]\357\203\201.txt" new file mode 100644 index 0000000..d35f779 --- /dev/null +++ "b/exported_docs/ros2/Using_Fast_DDS_Discovery_Server_as_discovery_protocol_[community-contributed]\357\203\201.txt" @@ -0,0 +1,254 @@ +Title: Using Fast DDS Discovery Server as discovery protocol [community-contributed] +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Discovery-Server/Discovery-Server.html +Section: Installation +-------------------------------------------------------------------------------- + +Using Fast DDS Discovery Server as discovery protocol [community-contributed]Goal:This tutorial will show how to launch ROS 2 Nodes using theFast DDS Discovery Serverdiscovery protocol.Tutorial level:AdvancedTime:20 minutesTable of ContentsBackgroundFast DDS Discovery Server v2PrerequisitesRun this tutorialSetup Discovery ServerLaunch listener nodeLaunch talker nodeDemonstrate Discovery Server executionVisualization toolrqt_graphAdvance use casesServer RedundancyBackup ServerDiscovery partitionsROS 2 IntrospectionDaemon’s related toolsNo Daemon toolsCompare Fast DDS Discovery Server with Simple Discovery ProtocolBackgroundStarting from ROS 2 Eloquent Elusor, theFast DDS Discovery Serverprotocol is a feature that offers a centralized dynamic discovery mechanism, as opposed to the distributed mechanism used in DDS by default. +This tutorial explains how to run some ROS 2 examples using the Fast DDS Discovery Server feature as discovery communication.In order to get more information about the available discovery configuration, please check thefollowing documentationor read theFast DDS Discovery Server specific documentation.TheSimple Discovery Protocolis the standard protocol defined in theDDS standard. +However, it has known disadvantages in some scenarios.It does notScaleefficiently, as the number of exchanged packets increases significantly as new nodes are added.It requiresmulticastingcapabilities that may not work reliably in some scenarios, e.g. WiFi.TheFast DDS Discovery Serverprovides a Client-Server Architecture that allows nodes to connect with each other using an intermediate server. +Each node functions as adiscovery client, sharing its info with one or morediscovery serversand receiving discovery information from it. +This reduces discovery-related network traffic and it does not require multicasting capabilities.These discovery servers can be independent, duplicated or connected with each other in order to create redundancy over the network and avoid having a single point of failure.Fast DDS Discovery Server v2The latest ROS 2 Foxy Fitzroy release (December 2020) included a new version, version 2 of the Fast DDS Discovery Server. +This version includes a new filter feature that further reduces the number of discovery messages sent. +This version uses the topic of the different nodes to decide if two nodes wish to communicate, or if they can be left unmatched (i.e. not discovering each other). +The following figure shows the decrease in discovery messages:This architecture reduces the number of messages sent between the server and clients dramatically. +In the following graph, the reduction in network traffic over the discovery phase for theRMF Clinic demonstrationis shown:In order to use this functionality, the discovery server can be configured using theXML configuration for Participants. +It is also possible to configure the discovery server using thefastddstooland anenvironment variable, which is the approach used in this tutorial. +For a more detailed explanation about the configuration of the discovery server, visitthe Fast DDS Discovery Server documentation.PrerequisitesThis tutorial assumes you have a ROS 2 Foxy (or newer)installation. +If your installation is using a ROS 2 version lower than Foxy, you cannot use thefastddstool. +Thus, in order to use the Discovery Server, you can update your repository to use a different Fast DDS version, or configure the discovery server using theFast DDS XML QoS configuration.Run this tutorialThetalker-listenerROS 2 demo creates atalkernode that publishes a “hello world” message every second, and alistenernode that listens to these messages.Bysourcing ROS 2you will get access to the CLI toolfastdds. +This tool gives access to thediscovery tool, which can be used to launch a discovery server. This server will manage the discovery process for the nodes that connect to it.ImportantDo not forget tosource ROS 2in every new terminal opened.Setup Discovery ServerStart by launching a discovery server with id 0, port 11811 (default port) and listening on all available interfaces.Open a new terminal and run:fastdds discovery --server-id 0Launch listener nodeExecute the listener demo, to listen to the/chattertopic.In a new terminal, set the environment variableROS_DISCOVERY_SERVERto the location of the discovery server. +(Do not forget to source ROS 2 in every new terminal)LinuxWindowsexport ROS_DISCOVERY_SERVER=127.0.0.1:11811set ROS_DISCOVERY_SERVER=127.0.0.1:11811Launch the listener node. Use the argument--remap__node:=listener_discovery_serverto change the node’s name for this tutorial.ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_discovery_serverThis will create a ROS 2 node, that will automatically create a client for the discovery server and connect to the server created previously to perform discovery, rather than using multicast.Launch talker nodeOpen a new terminal and set theROS_DISCOVERY_SERVERenvironment variable as before so that the node starts a discovery client.LinuxWindowsexport ROS_DISCOVERY_SERVER=127.0.0.1:11811set ROS_DISCOVERY_SERVER=127.0.0.1:11811ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_discovery_serverYou should now see the talker publishing “hello world” messages, and the listener receiving these messages.Demonstrate Discovery Server executionSo far, there is no evidence that this example and the standard talker-listener example are running differently. +To clearly demonstrate this, run another node that is not connected to the discovery server. +Run a new listener (listening in/chattertopic by default) in a new terminal and check that it is not connected to the talker already running.ros2 run demo_nodes_cpp listener --ros-args --remap __node:=simple_listenerThe new listener node should not be receiving the “hello world” messages.To finally verify that everything is running correctly, a new talker can be created using the simple discovery protocol (the default DDS distributed discovery mechanism) for discovery.ros2 run demo_nodes_cpp talker --ros-args --remap __node:=simple_talkerNow you should see thesimple_listenernode receiving the “hello world” messages fromsimple_talkerbut not the other messages fromtalker_discovery_server.Visualization toolrqt_graphTherqt_graphtool can be used to verify the nodes and structure of this example. +Remember, in order to userqt_graphwith the discovery server protocol (i.e., to see thelistener_discovery_serverandtalker_discovery_servernodes) theROS_DISCOVERY_SERVERenvironment variable must be set before launching it.Advance use casesThe following sections show different features of the discovery server that allow you to build a robust discovery server over the network.Server RedundancyBy usingfastddstool, multiple discovery servers can be created. +Discovery clients (ROS nodes) can connect to as many servers as desired. +This allows to have a redundant network that will work even if some servers or nodes shut down unexpectedly. +The figure below shows a simple architecture that provides server redundancy.In several terminals, run the following code to establish a communication with redundant servers.fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888--server-idNmeans server with id N. When referencing the servers withROS_DISCOVERY_SERVER, server0must be in first place and server1in second place.LinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talkerLinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listenerNow, if one of these servers fails, there will still be discovery capability available and nodes will still discover each other.Backup ServerThe Fast DDS Discovery Server allows creating a server with backup functionality. +This allows the server to restore the last state it saved in case of a shutdown.In different terminals, run the following code to establish a communication with a backed-up server.fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811 --backupLinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talkerLinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listenerSeveral backup files are created in the discovery server’s working directory (the directory it was launched in). +The twoSQLitefiles and twojsonfiles contain the information required to start a new server and restore the failed server’s state in case of failure, avoiding the need for the discovery process to happen again, and without losing information.Discovery partitionsCommunication with discovery servers can be split to create virtual partitions in the discovery information. +This means that two endpoints will only know about each other if there is a shared discovery server or a network of discovery servers between them. +We are going to execute an example with two independent servers. +The following figure shows the architecture.With this schemaListener1will be connected toTalker1andTalker2, as they shareServer1.Listener2will connect withTalker1as they shareServer2. +ButListener2will not hear the messages fromTalker2because they do not share any discovery server or discovery servers, including indirectly via connections between redundant discovery servers.Run the first server listening on localhost with the default port of 11811.fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811In another terminal run the second server listening on localhost using another port, in this case port 11888.fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888Now, run each node in a different terminal. UseROS_DISCOVERY_SERVERenvironment variable to decide which server they are connected to. Be aware that theids must match.LinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_1LinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888"ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_1LinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_2LinuxWindowsexport ROS_DISCOVERY_SERVER=";127.0.0.1:11888"set ROS_DISCOVERY_SERVER=";127.0.0.1:11888"ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_2We should see howListener1is receiving messages from both talker nodes, whileListener2is in a different partition fromTalker2and so does not receive messages from it.NoteOnce two endpoints (ROS nodes) have discovered each other, they do not need the discovery server network between them to listen to each other’s messages.ROS 2 IntrospectionTheROS 2 Command Line Interfacesupports several introspection tools to analyze the behavior of a ROS 2 network. +These tools (i.e.ros2bagrecord,ros2topiclist, etc.) are very helpful to understand a ROS 2 working network.Most of these tools use DDS simple discovery to exchange topic information with every existing participant (using simple discovery, every participant in the network is connected with each other). +However, the new Discovery Server v2 implements a network traffic reduction scheme that limits the discovery data between participants that do not share a topic. +This means that nodes will only receive topic’s discovery data if it has a writer or a reader for that topic. +As most ROS 2 CLIs need a node in the network (some of them rely on a running ROS 2 daemon, and some create their own nodes), using the Discovery Server v2 these nodes will not have all the network information, and thus their functionality will be limited.The Discovery Server v2 functionality allows every Participant to run as aSuper Client, a kind ofClientthat connects to aServer, from which it receives all the available discovery information (instead of just what it needs). +In this sense, ROS 2 introspection tools can be configured asSuper Client, thus being able to discover every entity that is using the Discovery Server protocol within the network.NoteIn this section we use the termParticipantas a DDS entity. Each DDSParticipantcorresponds with a ROS 2Context, a ROS 2 abstraction over DDS.Nodesare ROS 2 entities that rely on DDS communication interfaces:DataWriterandDataReader. +EachParticipantcan hold multiple ROS 2 Nodes. +For further details about these concepts, please visit theNode to Participant mapping design documentDaemon’s related toolsThe ROS 2 Daemon is used in several ROS 2 CLI introspection tools. +It creates its own Participant to add a ROS 2 Node to the network graph, in order to receive all the data sent. +In order for the ROS 2 CLI to work when using Discovery Server mechanism, the ROS 2 Daemon needs to be +configured asSuper Client. +Therefore, this section is devoted to explain how to use ROS 2 CLI with ROS 2 Daemon running as aSuper Client. +This will allow the Daemon to discover the entire Node graph, and to receive all topic and endpoint information. +To do so, a Fast DDS XML configuration file is used to configure the ROS 2 Daemon and CLI tools.Below you can find a XML configuration profile, which for this tutorial should be saved in the working directory as`super_client_configuration_file.xml`file. +This file will configure every new participant using it, as aSuper Client.SUPER_CLIENT
127.0.0.1
11811
NoteUnder theRemoteServertag, theprefixattribute value should be updated according to the server ID passed on the CLI (seeFast DDS CLI). +The value specified in the shown XML snippet corresponds to an ID of value 0.First of all, instantiate a Discovery Server usingFast DDS CLIspecifying an ID of value 0.fastdds discovery -i 0 -l 127.0.0.1 -p 11811Run a talker and a listener that will discover each other through the Server (notice thatROS_DISCOVERY_SERVERconfiguration is the same as the one insuper_client_configuration_file.xml).LinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listenerLinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talkerThen, instantiate a ROS 2 Daemon using theSuper Clientconfiguration (remember to source ROS 2 installation in every new terminal).LinuxWindowsexport FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xmlset FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xmlros2 daemon stopros2 daemon startros2 topic listros2 node info /talkerros2 topic info /chatterros2 topic echo /chatterWe can also see the Node’s Graph using the ROS 2 toolrqt_graphas follows (you may need to press the refresh button):LinuxWindowsexport FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xmlset FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xmlrqt_graphNo Daemon toolsSome ROS 2 CLI tools do not use the ROS 2 Daemon. +In order for these tools to connect with a Discovery Server and receive all the topics information they need to be instantiated as aSuper Clientthat connects to theServer.Following the previous configuration, build a simple system with a talker and a listener. +First, run aServer:fastdds discovery -i 0 -l 127.0.0.1 -p 11811Then, run the talker and listener in separate terminals:LinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listenerLinuxWindowsexport ROS_DISCOVERY_SERVER="127.0.0.1:11811"set ROS_DISCOVERY_SERVER="127.0.0.1:11811"ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talkerContinue using the ROS 2 CLI with--no-daemonoption with the new configuration. +New nodes will connect with the existing Server and will know every topic. +ExportingROS_DISCOVERY_SERVERis not needed as the ROS 2 tools will be configured through theFASTRTPS_DEFAULT_PROFILES_FILE.LinuxWindowsexport FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xmlset FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xmlros2 topic list --no-daemonros2 node info /talker --no-daemon --spin-time 2Compare Fast DDS Discovery Server with Simple Discovery ProtocolIn order to compare executing nodes using theSimple DiscoveryProtocol (the default DDS mechanism for distributed discovery) or theDiscovery Server, two scripts that execute a talker and many listeners and analyze the network traffic during this time are provided. +For this experiment,tsharkis required to be installed on your system. +The configuration file is mandatory in order to avoid using intraprocess mode.NoteThese scripts are only supported on Linux, and require a discovery server closure feature that is only available from versions newer than the version provided in ROS 2 Foxy. +In order to use this functionality, compile ROS 2 with Fast DDS v2.1.0 or higher.These scripts’ features are references for advanced purposes and their study is left to the user.bashnetworktrafficgeneratorpython3graphgeneratorXMLconfigurationRun the bash script with the path tosetup.bashfile to source ROS 2 as an argument. +This will generate the traffic trace for simple discovery. +Execute the same script with second argumentSERVER. +It will generate the trace for using the discovery server.NoteDepending on your configuration oftcpdump, this script may requiresudoprivileges to read traffic across your network device.After both executions are done, run the Python script to generate a graph similar to the one below.$exportFASTRTPS_DEFAULT_PROFILES_FILE="no_intraprocess_configuration.xml"$sudobashgenerate_discovery_packages.bash~/ros2/install/local_setup.bash$sudobashgenerate_discovery_packages.bash~/ros2/install/local_setup.bashSERVER$python3discovery_packets.pyThis graph is the result of a specific run of the experiment. +The reader can execute the scripts and generate their own results for comparison. +It can easily be seen that network traffic is reduced when using discovery service.The reduction in traffic is a result of avoiding every node announcing itself and waiting a response from every other node on the network. +This creates a huge amount of traffic in large architectures. +The reduction from this method increases with the number of nodes, making this architecture more scalable than the Simple Discovery Protocol approach.The new Fast DDS Discovery Server v2 is available sinceFast DDSv2.0.2, replacing the old discovery server. +In this new version, those nodes that do not share topics will automatically not discover each other, saving the whole discovery data required to connect them and their endpoints. +The experiment above does not show this case, but even so the massive reduction in traffic can be appreciated due to the hidden infrastructure topics of ROS 2 nodes. + +Code Examples: + +Language: unknown +fastdds discovery --server-id 0 + +Language: unknown +export ROS_DISCOVERY_SERVER=127.0.0.1:11811 + +Language: unknown +set ROS_DISCOVERY_SERVER=127.0.0.1:11811 + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_discovery_server + +Language: unknown +export ROS_DISCOVERY_SERVER=127.0.0.1:11811 + +Language: unknown +set ROS_DISCOVERY_SERVER=127.0.0.1:11811 + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_discovery_server + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=simple_listener + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=simple_talker + +Language: unknown +fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811 + +Language: unknown +fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888 + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener + +Language: unknown +fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811 --backup + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener + +Language: unknown +fastdds discovery --server-id 0 --ip-address 127.0.0.1 --port 11811 + +Language: unknown +fastdds discovery --server-id 1 --ip-address 127.0.0.1 --port 11888 + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_1 + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811;127.0.0.1:11888" + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_1 + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker_2 + +Language: unknown +export ROS_DISCOVERY_SERVER=";127.0.0.1:11888" + +Language: unknown +set ROS_DISCOVERY_SERVER=";127.0.0.1:11888" + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener_2 + +Language: unknown +SUPER_CLIENT
127.0.0.1
11811
+ +Language: unknown +fastdds discovery -i 0 -l 127.0.0.1 -p 11811 + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker + +Language: unknown +export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml + +Language: unknown +set FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml + +Language: unknown +ros2 daemon stopros2 daemon startros2 topic listros2 node info /talkerros2 topic info /chatterros2 topic echo /chatter + +Language: unknown +export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml + +Language: unknown +set FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml + +Language: unknown +rqt_graph + +Language: unknown +fastdds discovery -i 0 -l 127.0.0.1 -p 11811 + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp listener --ros-args --remap __node:=listener + +Language: unknown +export ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +set ROS_DISCOVERY_SERVER="127.0.0.1:11811" + +Language: unknown +ros2 run demo_nodes_cpp talker --ros-args --remap __node:=talker + +Language: unknown +export FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml + +Language: unknown +set FASTRTPS_DEFAULT_PROFILES_FILE=super_client_configuration_file.xml + +Language: unknown +ros2 topic list --no-daemonros2 node info /talker --no-daemon --spin-time 2 + +Language: unknown +$exportFASTRTPS_DEFAULT_PROFILES_FILE="no_intraprocess_configuration.xml"$sudobashgenerate_discovery_packages.bash~/ros2/install/local_setup.bash$sudobashgenerate_discovery_packages.bash~/ros2/install/local_setup.bashSERVER$python3discovery_packets.py diff --git "a/exported_docs/ros2/Using_Python,_XML,_and_YAML_for_ROS_2_Launch_Files\357\203\201.txt" "b/exported_docs/ros2/Using_Python,_XML,_and_YAML_for_ROS_2_Launch_Files\357\203\201.txt" new file mode 100644 index 0000000..862d848 --- /dev/null +++ "b/exported_docs/ros2/Using_Python,_XML,_and_YAML_for_ROS_2_Launch_Files\357\203\201.txt" @@ -0,0 +1,39 @@ +Title: Using Python, XML, and YAML for ROS 2 Launch Files +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Launch-file-different-formats.html +Section: Installation +-------------------------------------------------------------------------------- + +Using Python, XML, and YAML for ROS 2 Launch FilesTable of ContentsLaunch file examplesUsing the Launch files from the command linePython, XML, or YAML: Which should I use?ROS 2 launch files can be written in Python, XML, and YAML. +This guide shows how to use these different formats to accomplish the same task, as well as has some discussion on when to use each format.Launch file examplesBelow is a launch file implemented in Python, XML, and YAML. +Each launch file performs the following actions:Setup command line arguments with defaultsInclude another launch fileInclude another launch file in another namespaceStart a node and setting its namespaceStart a node, setting its namespace, and setting parameters in that node (using the args)Create a node to remap messages from one topic to anotherPythonXMLYAML# example_launch.pyimportosfromament_index_pythonimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.actionsimportGroupActionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch.substitutionsimportLaunchConfigurationfromlaunch.substitutionsimportTextSubstitutionfromlaunch_ros.actionsimportNodefromlaunch_ros.actionsimportPushROSNamespacefromlaunch_xml.launch_description_sourcesimportXMLLaunchDescriptionSourcefromlaunch_yaml.launch_description_sourcesimportYAMLLaunchDescriptionSourcedefgenerate_launch_description():# args that can be set from the command line or a default will be usedbackground_r_launch_arg=DeclareLaunchArgument("background_r",default_value=TextSubstitution(text="0"))background_g_launch_arg=DeclareLaunchArgument("background_g",default_value=TextSubstitution(text="255"))background_b_launch_arg=DeclareLaunchArgument("background_b",default_value=TextSubstitution(text="0"))chatter_py_ns_launch_arg=DeclareLaunchArgument("chatter_py_ns",default_value=TextSubstitution(text="chatter/py/ns"))chatter_xml_ns_launch_arg=DeclareLaunchArgument("chatter_xml_ns",default_value=TextSubstitution(text="chatter/xml/ns"))chatter_yaml_ns_launch_arg=DeclareLaunchArgument("chatter_yaml_ns",default_value=TextSubstitution(text="chatter/yaml/ns"))# include another launch filelaunch_include=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.py')))# include a Python launch file in the chatter_py_ns namespacelaunch_py_include_with_namespace=GroupAction(actions=[# push_ros_namespace first to set namespace of included nodes for following actionsPushROSNamespace('chatter_py_ns'),IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.py'))),])# include a xml launch file in the chatter_xml_ns namespacelaunch_xml_include_with_namespace=GroupAction(actions=[# push_ros_namespace first to set namespace of included nodes for following actionsPushROSNamespace('chatter_xml_ns'),IncludeLaunchDescription(XMLLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.xml'))),])# include a yaml launch file in the chatter_yaml_ns namespacelaunch_yaml_include_with_namespace=GroupAction(actions=[# push_ros_namespace first to set namespace of included nodes for following actionsPushROSNamespace('chatter_yaml_ns'),IncludeLaunchDescription(YAMLLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.yaml'))),])# start a turtlesim_node in the turtlesim1 namespaceturtlesim_node=Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim')# start another turtlesim_node in the turtlesim2 namespace# and use args to set parametersturtlesim_node_with_parameters=Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim',parameters=[{"background_r":LaunchConfiguration('background_r'),"background_g":LaunchConfiguration('background_g'),"background_b":LaunchConfiguration('background_b'),}])# perform remap so both turtles listen to the same command topicforward_turtlesim_commands_to_second_turtlesim_node=Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtlesim1/turtle1/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])returnLaunchDescription([background_r_launch_arg,background_g_launch_arg,background_b_launch_arg,chatter_py_ns_launch_arg,chatter_xml_ns_launch_arg,chatter_yaml_ns_launch_arg,launch_include,launch_py_include_with_namespace,launch_xml_include_with_namespace,launch_yaml_include_with_namespace,turtlesim_node,turtlesim_node_with_parameters,forward_turtlesim_commands_to_second_turtlesim_node,])# example_launch.yamllaunch:# args that can be set from the command line or a default will be used-arg:name:"background_r"default:"0"-arg:name:"background_g"default:"255"-arg:name:"background_b"default:"0"-arg:name:"chatter_py_ns"default:"chatter/py/ns"-arg:name:"chatter_xml_ns"default:"chatter/xml/ns"-arg:name:"chatter_yaml_ns"default:"chatter/yaml/ns"# include another launch file-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.py"# include a Python launch file in the chatter_py_ns namespace-group:-push_ros_namespace:namespace:"$(varchatter_py_ns)"-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.py"# include a xml launch file in the chatter_xml_ns namespace-group:-push_ros_namespace:namespace:"$(varchatter_xml_ns)"-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.xml"# include a yaml launch file in the chatter_yaml_ns namespace-group:-push_ros_namespace:namespace:"$(varchatter_yaml_ns)"-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.yaml"# start a turtlesim_node in the turtlesim1 namespace-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim1"# start another turtlesim_node in the turtlesim2 namespace and use args to set parameters-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim2"param:-name:"background_r"value:"$(varbackground_r)"-name:"background_g"value:"$(varbackground_g)"-name:"background_b"value:"$(varbackground_b)"# perform remap so both turtles listen to the same command topic-node:pkg:"turtlesim"exec:"mimic"name:"mimic"remap:-from:"/input/pose"to:"/turtlesim1/turtle1/pose"-from:"/output/cmd_vel"to:"/turtlesim2/turtle1/cmd_vel"Using the Launch files from the command lineLaunchingAny of the launch files above can be run withros2launch. +To try them locally, you can either create a new package and useros2 launch or run the file directly by specifying the path to the launch fileros2 launch Setting argumentsTo set the arguments that are passed to the launch file, you should usekey:=valuesyntax. +For example, you can set the value ofbackground_rin the following way:ros2 launch background_r:=255orros2 launch background_r:=255Controlling the turtlesTo test that the remapping is working, you can control the turtles by running the following command in another terminal:ros2 run turtlesim turtle_teleop_key --ros-args --remap __ns:=/turtlesim1Python, XML, or YAML: Which should I use?NoteLaunch files in ROS 1 were written in XML, so XML may be the most familiar to people coming from ROS 1. +To see what’s changed, you can visitMigrating Launch Files.For most applications the choice of which ROS 2 launch format comes down to developer preference. +However, if your launch file requires flexibility that you cannot achieve with XML or YAML, you can use Python to write your launch file. +Using Python for ROS 2 launch is more flexible because of following two reasons:Python is a scripting language, and thus you can leverage the language and its libraries in your launch files.ros2/launch(general launch features) andros2/launch_ros(ROS 2 specific launch features) are written in Python and thus you have lower level access to launch features that may not be exposed by XML and YAML.That being said, a launch file written in Python may be more complex and verbose than one in XML or YAML. + +Code Examples: + +Language: unknown +# example_launch.pyimportosfromament_index_pythonimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.actionsimportGroupActionfromlaunch.actionsimportIncludeLaunchDescriptionfromlaunch.launch_description_sourcesimportPythonLaunchDescriptionSourcefromlaunch.substitutionsimportLaunchConfigurationfromlaunch.substitutionsimportTextSubstitutionfromlaunch_ros.actionsimportNodefromlaunch_ros.actionsimportPushROSNamespacefromlaunch_xml.launch_description_sourcesimportXMLLaunchDescriptionSourcefromlaunch_yaml.launch_description_sourcesimportYAMLLaunchDescriptionSourcedefgenerate_launch_description():# args that can be set from the command line or a default will be usedbackground_r_launch_arg=DeclareLaunchArgument("background_r",default_value=TextSubstitution(text="0"))background_g_launch_arg=DeclareLaunchArgument("background_g",default_value=TextSubstitution(text="255"))background_b_launch_arg=DeclareLaunchArgument("background_b",default_value=TextSubstitution(text="0"))chatter_py_ns_launch_arg=DeclareLaunchArgument("chatter_py_ns",default_value=TextSubstitution(text="chatter/py/ns"))chatter_xml_ns_launch_arg=DeclareLaunchArgument("chatter_xml_ns",default_value=TextSubstitution(text="chatter/xml/ns"))chatter_yaml_ns_launch_arg=DeclareLaunchArgument("chatter_yaml_ns",default_value=TextSubstitution(text="chatter/yaml/ns"))# include another launch filelaunch_include=IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.py')))# include a Python launch file in the chatter_py_ns namespacelaunch_py_include_with_namespace=GroupAction(actions=[# push_ros_namespace first to set namespace of included nodes for following actionsPushROSNamespace('chatter_py_ns'),IncludeLaunchDescription(PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.py'))),])# include a xml launch file in the chatter_xml_ns namespacelaunch_xml_include_with_namespace=GroupAction(actions=[# push_ros_namespace first to set namespace of included nodes for following actionsPushROSNamespace('chatter_xml_ns'),IncludeLaunchDescription(XMLLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.xml'))),])# include a yaml launch file in the chatter_yaml_ns namespacelaunch_yaml_include_with_namespace=GroupAction(actions=[# push_ros_namespace first to set namespace of included nodes for following actionsPushROSNamespace('chatter_yaml_ns'),IncludeLaunchDescription(YAMLLaunchDescriptionSource(os.path.join(get_package_share_directory('demo_nodes_cpp'),'launch/topics/talker_listener_launch.yaml'))),])# start a turtlesim_node in the turtlesim1 namespaceturtlesim_node=Node(package='turtlesim',namespace='turtlesim1',executable='turtlesim_node',name='sim')# start another turtlesim_node in the turtlesim2 namespace# and use args to set parametersturtlesim_node_with_parameters=Node(package='turtlesim',namespace='turtlesim2',executable='turtlesim_node',name='sim',parameters=[{"background_r":LaunchConfiguration('background_r'),"background_g":LaunchConfiguration('background_g'),"background_b":LaunchConfiguration('background_b'),}])# perform remap so both turtles listen to the same command topicforward_turtlesim_commands_to_second_turtlesim_node=Node(package='turtlesim',executable='mimic',name='mimic',remappings=[('/input/pose','/turtlesim1/turtle1/pose'),('/output/cmd_vel','/turtlesim2/turtle1/cmd_vel'),])returnLaunchDescription([background_r_launch_arg,background_g_launch_arg,background_b_launch_arg,chatter_py_ns_launch_arg,chatter_xml_ns_launch_arg,chatter_yaml_ns_launch_arg,launch_include,launch_py_include_with_namespace,launch_xml_include_with_namespace,launch_yaml_include_with_namespace,turtlesim_node,turtlesim_node_with_parameters,forward_turtlesim_commands_to_second_turtlesim_node,]) + +Language: unknown + + +Language: unknown +# example_launch.yamllaunch:# args that can be set from the command line or a default will be used-arg:name:"background_r"default:"0"-arg:name:"background_g"default:"255"-arg:name:"background_b"default:"0"-arg:name:"chatter_py_ns"default:"chatter/py/ns"-arg:name:"chatter_xml_ns"default:"chatter/xml/ns"-arg:name:"chatter_yaml_ns"default:"chatter/yaml/ns"# include another launch file-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.py"# include a Python launch file in the chatter_py_ns namespace-group:-push_ros_namespace:namespace:"$(varchatter_py_ns)"-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.py"# include a xml launch file in the chatter_xml_ns namespace-group:-push_ros_namespace:namespace:"$(varchatter_xml_ns)"-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.xml"# include a yaml launch file in the chatter_yaml_ns namespace-group:-push_ros_namespace:namespace:"$(varchatter_yaml_ns)"-include:file:"$(find-pkg-sharedemo_nodes_cpp)/launch/topics/talker_listener_launch.yaml"# start a turtlesim_node in the turtlesim1 namespace-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim1"# start another turtlesim_node in the turtlesim2 namespace and use args to set parameters-node:pkg:"turtlesim"exec:"turtlesim_node"name:"sim"namespace:"turtlesim2"param:-name:"background_r"value:"$(varbackground_r)"-name:"background_g"value:"$(varbackground_g)"-name:"background_b"value:"$(varbackground_b)"# perform remap so both turtles listen to the same command topic-node:pkg:"turtlesim"exec:"mimic"name:"mimic"remap:-from:"/input/pose"to:"/turtlesim1/turtle1/pose"-from:"/output/cmd_vel"to:"/turtlesim2/turtle1/cmd_vel" + +Language: unknown +ros2 launch + +Language: unknown +ros2 launch + +Language: unknown +ros2 launch background_r:=255 + +Language: unknown +ros2 launch background_r:=255 + +Language: unknown +ros2 run turtlesim turtle_teleop_key --ros-args --remap __ns:=/turtlesim1 diff --git "a/exported_docs/ros2/Using_Python_Packages_with_ROS_2\357\203\201.txt" "b/exported_docs/ros2/Using_Python_Packages_with_ROS_2\357\203\201.txt" new file mode 100644 index 0000000..6bbad7a --- /dev/null +++ "b/exported_docs/ros2/Using_Python_Packages_with_ROS_2\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: Using Python Packages with ROS 2 +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Using-Python-Packages.html +Section: Installation +-------------------------------------------------------------------------------- + +Using Python Packages with ROS 2Goal:Explain how to interoperate with other Python packages from the ROS 2 ecosystem.ContentsInstalling viarosdepInstalling via a package managerInstalling via a virtual environmentNoteA cautionary note, if you intended to use pre-packaged binaries (eitherdebfiles, or the binary archive distributions), the Python interpreter must match what was used to build the original binaries. +If you intend to use something likevirtualenvorpipenv, make sure to use the system interpreter. +If you use something likeconda, it is very likely that the interpreter will not match the system interpreter and will be incompatible with ROS 2 binaries.Installing viarosdepThe fastest way to include third-party python packages is to use their corresponding rosdep keys, if available.rosdepkeys can be checked via:https://github.com/ros/rosdistro/blob/master/rosdep/base.yamlhttps://github.com/ros/rosdistro/blob/master/rosdep/python.yamlTheserosdepkeys can be added to yourpackage.xmlfile, which indicates to the build system that your package (and dependent packages) depend on those keys. +In a new workspace, you can also quickly install all rosdep keys with:rosdep install -yr ./path/to/your/workspaceIf there aren’t currentlyrosdepkeys for the package that you are interested in, it is possible to add them by following therosdep key contribution guide.To learn more about therosdeptool and how it works, consult therosdep documentation.Installing via a package managerIf you don’t want to make a rosdep key, but the package is available in your system package manager (egapt), you can install and use the package that way:sudo apt install python3-serialIf the package is available onThe Python Package Index (PyPI)and you want to install globally on your system:python3-mpipinstall-UpyserialIf the package is available on PyPI and you want to install locally to your user:python3 -m pip install -U --user pyserialInstalling via a virtual environmentFirst, create a Colcon workspace:mkdir -p ~/colcon_venv/srccd ~/colcon_venv/Then setup your virtual environment:#Makeavirtualenvandactivateitvirtualenv -p python3 ./venvsource ./venv/bin/activate#Makesurethatcolcondoesn’ttrytobuildthevenvtouch ./venv/COLCON_IGNORENext, install the Python packages that you want in your virtual environment:python3 -m pip install gtsam pyserial… etcNow you can build your workspace and run your python node that depends on packages installed in your virtual environment.#SourceJazzyandbuildsource /opt/ros/jazzy/setup.bashcolcon buildNoteIf you want to release your package using Bloom, you should add the packages you require torosdep, see therosdep key contribution guide. + +Code Examples: + +Language: unknown +rosdep install -yr ./path/to/your/workspace + +Language: unknown +sudo apt install python3-serial + +Language: unknown +python3-mpipinstall-Upyserial + +Language: unknown +python3 -m pip install -U --user pyserial + +Language: unknown +mkdir -p ~/colcon_venv/srccd ~/colcon_venv/ + +Language: unknown +#Makeavirtualenvandactivateitvirtualenv -p python3 ./venvsource ./venv/bin/activate#Makesurethatcolcondoesn’ttrytobuildthevenvtouch ./venv/COLCON_IGNORE + +Language: unknown +python3 -m pip install gtsam pyserial… etc + +Language: unknown +#SourceJazzyandbuildsource /opt/ros/jazzy/setup.bashcolcon build diff --git "a/exported_docs/ros2/Using_URDF_withrobot_state_publisher\357\203\201.txt" "b/exported_docs/ros2/Using_URDF_withrobot_state_publisher\357\203\201.txt" new file mode 100644 index 0000000..3a49cae --- /dev/null +++ "b/exported_docs/ros2/Using_URDF_withrobot_state_publisher\357\203\201.txt" @@ -0,0 +1,71 @@ +Title: Using URDF withrobot_state_publisher +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/URDF/Using-URDF-with-Robot-State-Publisher.html +Section: Installation +-------------------------------------------------------------------------------- + +Using URDF withrobot_state_publisherGoal:Simulate a walking robot modeled in URDF and view it in Rviz.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Create the URDF File3 Publish the state4 Create a launch file5 Edit the setup.py file6 Install the package7 View the resultsSummaryBackgroundThis tutorial will show you how to model a walking robot, publish the state as atf2message and view the simulation in Rviz. +First, we create the URDF model describing the robot assembly. +Next we write a node which simulates the motion and publishes the JointState and transforms. +We then userobot_state_publisherto publish the entire robot state to/tf2.Prerequisitesrviz2As always, don’t forget to source ROS 2 inevery new terminal you open.Tasks1 Create a packageCreate the directory:LinuxmacOSWindowsmkdir -p second_ros2_ws/srcmkdir -p second_ros2_ws/srcmd second_ros2_ws/srcThen create the package:cd second_ros2_ws/srcros2 pkg create --build-type ament_python --license Apache-2.0 urdf_tutorial_r2d2 --dependencies rclpycd urdf_tutorial_r2d2You should now see aurdf_tutorial_r2d2folder. +Next you will make several changes to it.2 Create the URDF FileCreate the directory where we will store some assets:LinuxmacOSWindowsmkdir -p urdfmkdir -p urdfmd urdfDownload theURDFfileand save it assecond_ros2_ws/src/urdf_tutorial_r2d2/urdf/r2d2.urdf.xml. +Download theRvizconfigurationfileand save it assecond_ros2_ws/src/urdf_tutorial_r2d2/urdf/r2d2.rviz.3 Publish the stateNow we need a method for specifying what state the robot is in. +To do this, we must specify all three joints and the overall odometry.Fire up your favorite editor and paste the following code intosecond_ros2_ws/src/urdf_tutorial_r2d2/urdf_tutorial_r2d2/state_publisher.pyfrommathimportsin,cos,piimportrclpyfromrclpy.nodeimportNodefromrclpy.qosimportQoSProfilefromgeometry_msgs.msgimportQuaternionfromsensor_msgs.msgimportJointStatefromtf2_rosimportTransformBroadcaster,TransformStampedclassStatePublisher(Node):def__init__(self):rclpy.init()super().__init__('state_publisher')qos_profile=QoSProfile(depth=10)self.joint_pub=self.create_publisher(JointState,'joint_states',qos_profile)self.broadcaster=TransformBroadcaster(self,qos=qos_profile)self.nodeName=self.get_name()self.get_logger().info("{0}started".format(self.nodeName))degree=pi/180.0loop_rate=self.create_rate(30)# robot statetilt=0.tinc=degreeswivel=0.angle=0.height=0.hinc=0.005# message declarationsodom_trans=TransformStamped()odom_trans.header.frame_id='odom'odom_trans.child_frame_id='axis'joint_state=JointState()try:whilerclpy.ok():rclpy.spin_once(self)# update joint_statenow=self.get_clock().now()joint_state.header.stamp=now.to_msg()joint_state.name=['swivel','tilt','periscope']joint_state.position=[swivel,tilt,height]# update transform# (moving in a circle with radius=2)odom_trans.header.stamp=now.to_msg()odom_trans.transform.translation.x=cos(angle)*2odom_trans.transform.translation.y=sin(angle)*2odom_trans.transform.translation.z=0.7odom_trans.transform.rotation=\euler_to_quaternion(0,0,angle+pi/2)# roll,pitch,yaw# send the joint state and transformself.joint_pub.publish(joint_state)self.broadcaster.sendTransform(odom_trans)# Create new robot statetilt+=tinciftilt<-0.5ortilt>0.0:tinc*=-1height+=hincifheight>0.2orheight<0.0:hinc*=-1swivel+=degreeangle+=degree/4# This will adjust as needed per iterationloop_rate.sleep()exceptKeyboardInterrupt:passdefeuler_to_quaternion(roll,pitch,yaw):qx=sin(roll/2)*cos(pitch/2)*cos(yaw/2)-cos(roll/2)*sin(pitch/2)*sin(yaw/2)qy=cos(roll/2)*sin(pitch/2)*cos(yaw/2)+sin(roll/2)*cos(pitch/2)*sin(yaw/2)qz=cos(roll/2)*cos(pitch/2)*sin(yaw/2)-sin(roll/2)*sin(pitch/2)*cos(yaw/2)qw=cos(roll/2)*cos(pitch/2)*cos(yaw/2)+sin(roll/2)*sin(pitch/2)*sin(yaw/2)returnQuaternion(x=qx,y=qy,z=qz,w=qw)defmain():node=StatePublisher()if__name__=='__main__':main()4 Create a launch fileCreate a newsecond_ros2_ws/src/urdf_tutorial_r2d2/launchfolder. +Open your editor and paste the following code, saving it assecond_ros2_ws/src/urdf_tutorial_r2d2/launch/demo_launch.pyimportosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():use_sim_time=LaunchConfiguration('use_sim_time',default='false')urdf_file_name='r2d2.urdf.xml'urdf=os.path.join(get_package_share_directory('urdf_tutorial_r2d2'),urdf_file_name)withopen(urdf,'r')asinfp:robot_desc=infp.read()returnLaunchDescription([DeclareLaunchArgument('use_sim_time',default_value='false',description='Use simulation (Gazebo) clock if true'),Node(package='robot_state_publisher',executable='robot_state_publisher',name='robot_state_publisher',output='screen',parameters=[{'use_sim_time':use_sim_time,'robot_description':robot_desc}],arguments=[urdf]),Node(package='urdf_tutorial_r2d2',executable='state_publisher',name='state_publisher',output='screen'),])5 Edit the setup.py fileYou must tell thecolconbuild tool how to install your Python package. +Edit thesecond_ros2_ws/src/urdf_tutorial_r2d2/setup.pyfile as follows:include these import statementsimportosfromglobimportglobfromsetuptoolsimportsetupfromsetuptoolsimportfind_packagesappend these 2 lines insidedata_filesdata_files=[...(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.[pxy][yma]*'))),(os.path.join('share',package_name),glob('urdf/*')),],modify theentry_pointstable so you can later run ‘state_publisher’ from a console'console_scripts':['state_publisher = urdf_tutorial_r2d2.state_publisher:main'],Save thesetup.pyfile with your changes.6 Install the packagecd second_ros2_wscolcon build --symlink-install --packages-select urdf_tutorial_r2d2Source the setup files:LinuxmacOSWindowssource install/setup.bashsource install/setup.bashcall install/setup.bat7 View the resultsLaunch the packageros2 launch urdf_tutorial_r2d2 demo_launch.pyOpen a new terminal, the run Rviz usingrviz2 -d second_ros2_ws/install/urdf_tutorial_r2d2/share/urdf_tutorial_r2d2/r2d2.rvizSee theUser Guidefor details on how to use Rviz.SummaryYou created aJointStatepublisher node and coupled it withrobot_state_publisherto simulate a walking robot. +The code used in these examples is originally fromhere.Credit is given to the authors of thisROS 1 tutorialfrom which some content was reused. + +Code Examples: + +Language: unknown +mkdir -p second_ros2_ws/src + +Language: unknown +mkdir -p second_ros2_ws/src + +Language: unknown +md second_ros2_ws/src + +Language: unknown +cd second_ros2_ws/srcros2 pkg create --build-type ament_python --license Apache-2.0 urdf_tutorial_r2d2 --dependencies rclpycd urdf_tutorial_r2d2 + +Language: unknown +mkdir -p urdf + +Language: unknown +mkdir -p urdf + +Language: unknown +md urdf + +Language: unknown +frommathimportsin,cos,piimportrclpyfromrclpy.nodeimportNodefromrclpy.qosimportQoSProfilefromgeometry_msgs.msgimportQuaternionfromsensor_msgs.msgimportJointStatefromtf2_rosimportTransformBroadcaster,TransformStampedclassStatePublisher(Node):def__init__(self):rclpy.init()super().__init__('state_publisher')qos_profile=QoSProfile(depth=10)self.joint_pub=self.create_publisher(JointState,'joint_states',qos_profile)self.broadcaster=TransformBroadcaster(self,qos=qos_profile)self.nodeName=self.get_name()self.get_logger().info("{0}started".format(self.nodeName))degree=pi/180.0loop_rate=self.create_rate(30)# robot statetilt=0.tinc=degreeswivel=0.angle=0.height=0.hinc=0.005# message declarationsodom_trans=TransformStamped()odom_trans.header.frame_id='odom'odom_trans.child_frame_id='axis'joint_state=JointState()try:whilerclpy.ok():rclpy.spin_once(self)# update joint_statenow=self.get_clock().now()joint_state.header.stamp=now.to_msg()joint_state.name=['swivel','tilt','periscope']joint_state.position=[swivel,tilt,height]# update transform# (moving in a circle with radius=2)odom_trans.header.stamp=now.to_msg()odom_trans.transform.translation.x=cos(angle)*2odom_trans.transform.translation.y=sin(angle)*2odom_trans.transform.translation.z=0.7odom_trans.transform.rotation=\euler_to_quaternion(0,0,angle+pi/2)# roll,pitch,yaw# send the joint state and transformself.joint_pub.publish(joint_state)self.broadcaster.sendTransform(odom_trans)# Create new robot statetilt+=tinciftilt<-0.5ortilt>0.0:tinc*=-1height+=hincifheight>0.2orheight<0.0:hinc*=-1swivel+=degreeangle+=degree/4# This will adjust as needed per iterationloop_rate.sleep()exceptKeyboardInterrupt:passdefeuler_to_quaternion(roll,pitch,yaw):qx=sin(roll/2)*cos(pitch/2)*cos(yaw/2)-cos(roll/2)*sin(pitch/2)*sin(yaw/2)qy=cos(roll/2)*sin(pitch/2)*cos(yaw/2)+sin(roll/2)*cos(pitch/2)*sin(yaw/2)qz=cos(roll/2)*cos(pitch/2)*sin(yaw/2)-sin(roll/2)*sin(pitch/2)*cos(yaw/2)qw=cos(roll/2)*cos(pitch/2)*cos(yaw/2)+sin(roll/2)*sin(pitch/2)*sin(yaw/2)returnQuaternion(x=qx,y=qy,z=qz,w=qw)defmain():node=StatePublisher()if__name__=='__main__':main() + +Language: unknown +importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():use_sim_time=LaunchConfiguration('use_sim_time',default='false')urdf_file_name='r2d2.urdf.xml'urdf=os.path.join(get_package_share_directory('urdf_tutorial_r2d2'),urdf_file_name)withopen(urdf,'r')asinfp:robot_desc=infp.read()returnLaunchDescription([DeclareLaunchArgument('use_sim_time',default_value='false',description='Use simulation (Gazebo) clock if true'),Node(package='robot_state_publisher',executable='robot_state_publisher',name='robot_state_publisher',output='screen',parameters=[{'use_sim_time':use_sim_time,'robot_description':robot_desc}],arguments=[urdf]),Node(package='urdf_tutorial_r2d2',executable='state_publisher',name='state_publisher',output='screen'),]) + +Language: unknown +importosfromglobimportglobfromsetuptoolsimportsetupfromsetuptoolsimportfind_packages + +Language: unknown +data_files=[...(os.path.join('share',package_name,'launch'),glob(os.path.join('launch','*launch.[pxy][yma]*'))),(os.path.join('share',package_name),glob('urdf/*')),], + +Language: unknown +'console_scripts':['state_publisher = urdf_tutorial_r2d2.state_publisher:main'], + +Language: unknown +cd second_ros2_wscolcon build --symlink-install --packages-select urdf_tutorial_r2d2 + +Language: unknown +source install/setup.bash + +Language: unknown +source install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 launch urdf_tutorial_r2d2 demo_launch.py + +Language: unknown +rviz2 -d second_ros2_ws/install/urdf_tutorial_r2d2/share/urdf_tutorial_r2d2/r2d2.rviz diff --git "a/exported_docs/ros2/Using_event_handlers\357\203\201.txt" "b/exported_docs/ros2/Using_event_handlers\357\203\201.txt" new file mode 100644 index 0000000..9a11724 --- /dev/null +++ "b/exported_docs/ros2/Using_event_handlers\357\203\201.txt" @@ -0,0 +1,45 @@ +Title: Using event handlers +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Launch/Using-Event-Handlers.html +Section: Installation +-------------------------------------------------------------------------------- + +Using event handlersGoal:Learn about event handlers in ROS 2 launch filesTutorial level:IntermediateTime:15 minutesTable of ContentsBackgroundPrerequisitesUsing event handlers1 Event handlers example launch fileBuild the packageLaunching exampleDocumentationSummaryBackgroundLaunch in ROS 2 is a system that executes and manages user-defined processes. +It is responsible for monitoring the state of processes it launched, as well as reporting and reacting to changes in the state of those processes. +These changes are called events and can be handled by registering an event handler with the launch system. +Event handlers can be registered for specific events and can be useful for monitoring the state of processes. +Additionally, they can be used to define a complex set of rules which can be used to dynamically modify the launch file.This tutorial shows usage examples of event handlers in ROS 2 launch files.PrerequisitesThis tutorial uses theturtlesimpackage. +This tutorial also assumes you havecreated a new packageof build typeament_pythoncalledlaunch_tutorial.This tutorial extends the code shown in theUsing substitutions in launch filestutorial.Using event handlers1 Event handlers example launch fileCreate a new file calledexample_event_handlers_launch.pyfile in thelaunchfolder of thelaunch_tutorialpackage.fromlaunch_ros.actionsimportNodefromlaunchimportLaunchDescriptionfromlaunch.actionsimport(DeclareLaunchArgument,EmitEvent,ExecuteProcess,LogInfo,RegisterEventHandler,TimerAction)fromlaunch.conditionsimportIfConditionfromlaunch.event_handlersimport(OnExecutionComplete,OnProcessExit,OnProcessIO,OnProcessStart,OnShutdown)fromlaunch.eventsimportShutdownfromlaunch.substitutionsimport(EnvironmentVariable,FindExecutable,LaunchConfiguration,LocalSubstitution,PythonExpression)defgenerate_launch_description():turtlesim_ns=LaunchConfiguration('turtlesim_ns')use_provided_red=LaunchConfiguration('use_provided_red')new_background_r=LaunchConfiguration('new_background_r')turtlesim_ns_launch_arg=DeclareLaunchArgument('turtlesim_ns',default_value='turtlesim1')use_provided_red_launch_arg=DeclareLaunchArgument('use_provided_red',default_value='False')new_background_r_launch_arg=DeclareLaunchArgument('new_background_r',default_value='200')turtlesim_node=Node(package='turtlesim',namespace=turtlesim_ns,executable='turtlesim_node',name='sim')spawn_turtle=ExecuteProcess(cmd=[[FindExecutable(name='ros2'),' service call ',turtlesim_ns,'/spawn ','turtlesim/srv/Spawn ','"{x: 2, y: 2, theta: 0.2}"']],shell=True)change_background_r=ExecuteProcess(cmd=[[FindExecutable(name='ros2'),' param set ',turtlesim_ns,'/sim background_r ','120']],shell=True)change_background_r_conditioned=ExecuteProcess(condition=IfCondition(PythonExpression([new_background_r,' == 200',' and ',use_provided_red])),cmd=[[FindExecutable(name='ros2'),' param set ',turtlesim_ns,'/sim background_r ',new_background_r]],shell=True)returnLaunchDescription([turtlesim_ns_launch_arg,use_provided_red_launch_arg,new_background_r_launch_arg,turtlesim_node,RegisterEventHandler(OnProcessStart(target_action=turtlesim_node,on_start=[LogInfo(msg='Turtlesim started, spawning turtle'),spawn_turtle])),RegisterEventHandler(OnProcessIO(target_action=spawn_turtle,on_stdout=lambdaevent:LogInfo(msg='Spawn request says "{}"'.format(event.text.decode().strip())))),RegisterEventHandler(OnExecutionComplete(target_action=spawn_turtle,on_completion=[LogInfo(msg='Spawn finished'),change_background_r,TimerAction(period=2.0,actions=[change_background_r_conditioned],)])),RegisterEventHandler(OnProcessExit(target_action=turtlesim_node,on_exit=[LogInfo(msg=(EnvironmentVariable(name='USER'),' closed the turtlesim window')),EmitEvent(event=Shutdown(reason='Window closed'))])),RegisterEventHandler(OnShutdown(on_shutdown=[LogInfo(msg=['Launch was asked to shutdown: ',LocalSubstitution('event.reason')])])),])RegisterEventHandleractions for theOnProcessStart,OnProcessIO,OnExecutionComplete,OnProcessExit, andOnShutdownevents were defined in the launch description.TheOnProcessStartevent handler is used to register a callback function that is executed when the turtlesim node starts. +It logs a message to the console and executes thespawn_turtleaction when the turtlesim node starts.RegisterEventHandler(OnProcessStart(target_action=turtlesim_node,on_start=[LogInfo(msg='Turtlesim started, spawning turtle'),spawn_turtle])),TheOnProcessIOevent handler is used to register a callback function that is executed when thespawn_turtleaction writes to its standard output. +It logs the result of the spawn request.RegisterEventHandler(OnProcessIO(target_action=spawn_turtle,on_stdout=lambdaevent:LogInfo(msg='Spawn request says "{}"'.format(event.text.decode().strip())))),TheOnExecutionCompleteevent handler is used to register a callback function that is executed when thespawn_turtleaction completes. +It logs a message to the console and executes thechange_background_randchange_background_r_conditionedactions when the spawn action completes.RegisterEventHandler(OnExecutionComplete(target_action=spawn_turtle,on_completion=[LogInfo(msg='Spawn finished'),change_background_r,TimerAction(period=2.0,actions=[change_background_r_conditioned],)])),TheOnProcessExitevent handler is used to register a callback function that is executed when the turtlesim node exits. +It logs a message to the console and executes theEmitEventaction to emit aShutdownevent when the turtlesim node exits. +It means that the launch process will shutdown when the turtlesim window is closed.RegisterEventHandler(OnProcessExit(target_action=turtlesim_node,on_exit=[LogInfo(msg=(EnvironmentVariable(name='USER'),' closed the turtlesim window')),EmitEvent(event=Shutdown(reason='Window closed'))])),Finally, theOnShutdownevent handler is used to register a callback function that is executed when the launch file is asked to shutdown. +It logs a message to the console why the launch file is asked to shutdown. +It logs the message with a reason for shutdown like the closure of turtlesim window orctrl-csignal made by the user.RegisterEventHandler(OnShutdown(on_shutdown=[LogInfo(msg=['Launch was asked to shutdown: ',LocalSubstitution('event.reason')])])),Build the packageGo to the root of the workspace, and build the package:colcon buildAlso remember to source the workspace after building.Launching exampleNow you can launch theexample_event_handlers_launch.pyfile using theros2launchcommand.ros2 launch launch_tutorial example_event_handlers_launch.py turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200This will do the following:Start a turtlesim node with a blue backgroundSpawn the second turtleChange the color to purpleChange the color to pink after two seconds if the providedbackground_rargument is200anduse_provided_redargument isTrueShutdown the launch file when the turtlesim window is closedAdditionally, it will log messages to the console when:The turtlesim node startsThe spawn action is executedThechange_background_raction is executedThechange_background_r_conditionedaction is executedThe turtlesim node exitsThe launch process is asked to shutdown.DocumentationThe launch documentationprovides detailed information about available event handlers.SummaryIn this tutorial, you learned about using event handlers in launch files. +You learned about their syntax and usage examples to define a complex set of rules to dynamically modify launch files. + +Code Examples: + +Language: unknown +fromlaunch_ros.actionsimportNodefromlaunchimportLaunchDescriptionfromlaunch.actionsimport(DeclareLaunchArgument,EmitEvent,ExecuteProcess,LogInfo,RegisterEventHandler,TimerAction)fromlaunch.conditionsimportIfConditionfromlaunch.event_handlersimport(OnExecutionComplete,OnProcessExit,OnProcessIO,OnProcessStart,OnShutdown)fromlaunch.eventsimportShutdownfromlaunch.substitutionsimport(EnvironmentVariable,FindExecutable,LaunchConfiguration,LocalSubstitution,PythonExpression)defgenerate_launch_description():turtlesim_ns=LaunchConfiguration('turtlesim_ns')use_provided_red=LaunchConfiguration('use_provided_red')new_background_r=LaunchConfiguration('new_background_r')turtlesim_ns_launch_arg=DeclareLaunchArgument('turtlesim_ns',default_value='turtlesim1')use_provided_red_launch_arg=DeclareLaunchArgument('use_provided_red',default_value='False')new_background_r_launch_arg=DeclareLaunchArgument('new_background_r',default_value='200')turtlesim_node=Node(package='turtlesim',namespace=turtlesim_ns,executable='turtlesim_node',name='sim')spawn_turtle=ExecuteProcess(cmd=[[FindExecutable(name='ros2'),' service call ',turtlesim_ns,'/spawn ','turtlesim/srv/Spawn ','"{x: 2, y: 2, theta: 0.2}"']],shell=True)change_background_r=ExecuteProcess(cmd=[[FindExecutable(name='ros2'),' param set ',turtlesim_ns,'/sim background_r ','120']],shell=True)change_background_r_conditioned=ExecuteProcess(condition=IfCondition(PythonExpression([new_background_r,' == 200',' and ',use_provided_red])),cmd=[[FindExecutable(name='ros2'),' param set ',turtlesim_ns,'/sim background_r ',new_background_r]],shell=True)returnLaunchDescription([turtlesim_ns_launch_arg,use_provided_red_launch_arg,new_background_r_launch_arg,turtlesim_node,RegisterEventHandler(OnProcessStart(target_action=turtlesim_node,on_start=[LogInfo(msg='Turtlesim started, spawning turtle'),spawn_turtle])),RegisterEventHandler(OnProcessIO(target_action=spawn_turtle,on_stdout=lambdaevent:LogInfo(msg='Spawn request says "{}"'.format(event.text.decode().strip())))),RegisterEventHandler(OnExecutionComplete(target_action=spawn_turtle,on_completion=[LogInfo(msg='Spawn finished'),change_background_r,TimerAction(period=2.0,actions=[change_background_r_conditioned],)])),RegisterEventHandler(OnProcessExit(target_action=turtlesim_node,on_exit=[LogInfo(msg=(EnvironmentVariable(name='USER'),' closed the turtlesim window')),EmitEvent(event=Shutdown(reason='Window closed'))])),RegisterEventHandler(OnShutdown(on_shutdown=[LogInfo(msg=['Launch was asked to shutdown: ',LocalSubstitution('event.reason')])])),]) + +Language: unknown +RegisterEventHandler(OnProcessStart(target_action=turtlesim_node,on_start=[LogInfo(msg='Turtlesim started, spawning turtle'),spawn_turtle])), + +Language: unknown +RegisterEventHandler(OnProcessIO(target_action=spawn_turtle,on_stdout=lambdaevent:LogInfo(msg='Spawn request says "{}"'.format(event.text.decode().strip())))), + +Language: unknown +RegisterEventHandler(OnExecutionComplete(target_action=spawn_turtle,on_completion=[LogInfo(msg='Spawn finished'),change_background_r,TimerAction(period=2.0,actions=[change_background_r_conditioned],)])), + +Language: unknown +RegisterEventHandler(OnProcessExit(target_action=turtlesim_node,on_exit=[LogInfo(msg=(EnvironmentVariable(name='USER'),' closed the turtlesim window')),EmitEvent(event=Shutdown(reason='Window closed'))])), + +Language: unknown +RegisterEventHandler(OnShutdown(on_shutdown=[LogInfo(msg=['Launch was asked to shutdown: ',LocalSubstitution('event.reason')])])), + +Language: unknown +colcon build + +Language: unknown +ros2 launch launch_tutorial example_event_handlers_launch.py turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200 diff --git "a/exported_docs/ros2/Using_parameters_in_a_class_(C++)\357\203\201.txt" "b/exported_docs/ros2/Using_parameters_in_a_class_(C++)\357\203\201.txt" new file mode 100644 index 0000000..a6ddcb4 --- /dev/null +++ "b/exported_docs/ros2/Using_parameters_in_a_class_(C++)\357\203\201.txt" @@ -0,0 +1,124 @@ +Title: Using parameters in a class (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-CPP.html +Section: Installation +-------------------------------------------------------------------------------- + +Using parameters in a class (C++)Goal:Create and run a class with ROS parameters using C++.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the C++ node3 Build and runSummaryNext stepsBackgroundWhen making your ownnodesyou will sometimes need to add parameters that can be set from the launch file.This tutorial will show you how to create those parameters in a C++ class, and how to set them in a launch file.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package. +You have also learned aboutparametersand their function in a ROS 2 system.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Followthese instructionsto create a new workspace namedros2_ws.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +Navigate intoros2_ws/srcand create a new package:ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_parameters --dependencies rclcppYour terminal will return a message verifying the creation of your packagecpp_parametersand all its necessary files and folders.The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xmlorCMakeLists.txt.As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.C++parametertutorialYourNameApache-2.02 Write the C++ nodeInside theros2_ws/src/cpp_parameters/srcdirectory, create a new file calledcpp_parameters_node.cppand paste the following code within:#include#include#include#includeusingnamespacestd::chrono_literals;classMinimalParam:publicrclcpp::Node{public:MinimalParam():Node("minimal_param_node"){this->declare_parameter("my_parameter","world");autotimer_callback=[this](){std::stringmy_param=this->get_parameter("my_parameter").as_string();RCLCPP_INFO(this->get_logger(),"Hello %s!",my_param.c_str());std::vectorall_new_parameters{rclcpp::Parameter("my_parameter","world")};this->set_parameters(all_new_parameters);};timer_=this->create_wall_timer(1000ms,timer_callback);}private:rclcpp::TimerBase::SharedPtrtimer_;};intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.1 Examine the codeThe#includestatements at the top are the package dependencies.The next piece of code creates the class and the constructor. +The first line of this constructor creates a parameter with the namemy_parameterand a default value ofworld. +The parameter type is inferred from the default value, so in this case it would be set to a string type. +Next, alambda functioncalledtimer_callbackis declared. +It performs a by-reference capture of the current objectthis, takes no input arguments and returns void. +The first line of ourtimer_callbackfunction gets the parametermy_parameterfrom the node, and stores it inmy_param. +Then theRCLCPP_INFOfunction ensures the event is logged. +Theset_parametersfunction sets the parametermy_parameterback to the default string valueworld. +In the case that the user changed the parameter externally, this ensures it is always reset back to the original. +In the end,timer_is initialized with a period of 1000ms, which causes thetimer_callbackfunction to be executed once a second.classMinimalParam:publicrclcpp::Node{public:MinimalParam():Node("minimal_param_node"){this->declare_parameter("my_parameter","world");autotimer_callback=[this](){std::stringmy_param=this->get_parameter("my_parameter").as_string();RCLCPP_INFO(this->get_logger(),"Hello %s!",my_param.c_str());std::vectorall_new_parameters{rclcpp::Parameter("my_parameter","world")};this->set_parameters(all_new_parameters);};timer_=this->create_wall_timer(1000ms,timer_callback);}Last is the declaration oftimer_.private:rclcpp::TimerBase::SharedPtrtimer_;Following ourMinimalParamis ourmain. +Here ROS 2 is initialized, an instance of theMinimalParamclass is constructed, andrclcpp::spinstarts processing data from the node.intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.1.1 (Optional) Add ParameterDescriptorOptionally, you can set a descriptor for the parameter. +Descriptors allow you to specify a text description of the parameter and its constraints, like making it read-only, specifying a range, etc. +For that to work, the code in the constructor has to be changed to:// ...classMinimalParam:publicrclcpp::Node{public:MinimalParam():Node("minimal_param_node"){autoparam_desc=rcl_interfaces::msg::ParameterDescriptor{};param_desc.description="This parameter is mine!";this->declare_parameter("my_parameter","world",param_desc);autotimer_callback=[this](){std::stringmy_param=this->get_parameter("my_parameter").as_string();RCLCPP_INFO(this->get_logger(),"Hello %s!",my_param.c_str());std::vectorall_new_parameters{rclcpp::Parameter("my_parameter","world")};this->set_parameters(all_new_parameters);};timer_=this->create_wall_timer(1000ms,timer_callback);}The rest of the code remains the same. +Once you run the node, you can then runros2paramdescribe/minimal_param_nodemy_parameterto see the type and description.2.2 Add executableNow open theCMakeLists.txtfile. Below the dependencyfind_package(rclcppREQUIRED)add the following lines of code.add_executable(minimal_param_nodesrc/cpp_parameters_node.cpp)ament_target_dependencies(minimal_param_noderclcpp)install(TARGETSminimal_param_nodeDESTINATIONlib/${PROJECT_NAME})3 Build and runIt’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Navigate back to the root of your workspace,ros2_ws, and build your new package:LinuxmacOSWindowscolcon build --packages-select cpp_parameterscolcon build --packages-select cpp_parameterscolcon build --merge-install --packages-select cpp_parametersOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the node:ros2 run cpp_parameters minimal_param_nodeThe terminal should return the following message every second:[INFO] [minimal_param_node]: Hello world!Now you can see the default value of your parameter, but you want to be able to set it yourself. +There are two ways to accomplish this.3.1 Change via the consoleThis part will use the knowledge you have gained from thetutorial about parametersand apply it to the node you have just created.Make sure the node is running:ros2 run cpp_parameters minimal_param_nodeOpen another terminal, source the setup files from insideros2_wsagain, and enter the following line:ros2 param listThere you will see the custom parametermy_parameter. +To change it, simply run the following line in the console:ros2 param set /minimal_param_node my_parameter earthYou know it went well if you got the outputSetparametersuccessful. +If you look at the other terminal, you should see the output change to[INFO][minimal_param_node]:Helloearth!3.2 Change via a launch fileYou can also set the parameter in a launch file, but first you will need to add the launch directory. +Inside theros2_ws/src/cpp_parameters/directory, create a new directory calledlaunch. +In there, create a new file calledcpp_parameters_launch.pyfromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package="cpp_parameters",executable="minimal_param_node",name="custom_minimal_param_node",output="screen",emulate_tty=True,parameters=[{"my_parameter":"earth"}])])Here you can see that we setmy_parametertoearthwhen we launch our nodeminimal_param_node. +By adding the two lines below, we ensure our output is printed in our console.output="screen",emulate_tty=True,Now open theCMakeLists.txtfile. +Below the lines you added earlier, add the following lines of code.install(DIRECTORY launchDESTINATION share/${PROJECT_NAME})Open a console and navigate to the root of your workspace,ros2_ws, and build your new package:LinuxmacOSWindowscolcon build --packages-select cpp_parameterscolcon build --packages-select cpp_parameterscolcon build --merge-install --packages-select cpp_parametersThen source the setup files in a new terminal:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the node using the launch file we have just created:ros2 launch cpp_parameters cpp_parameters_launch.pyThe terminal should return the following message the first time:[INFO] [custom_minimal_param_node]: Hello earth!Further outputs should show[INFO][minimal_param_node]:Helloworld!every second.SummaryYou created a node with a custom parameter that can be set either from a launch file or the command line. +You added the dependencies, executables, and a launch file to the package configuration files so that you could build and run them, and see the parameter in action.Next stepsNow that you have some packages and ROS 2 systems of your own, thenext tutorialwill show you how to examine issues in your environment and systems in case you have problems. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_parameters --dependencies rclcpp + +Language: unknown +C++parametertutorialYourNameApache-2.0 + +Language: unknown +#include#include#include#includeusingnamespacestd::chrono_literals;classMinimalParam:publicrclcpp::Node{public:MinimalParam():Node("minimal_param_node"){this->declare_parameter("my_parameter","world");autotimer_callback=[this](){std::stringmy_param=this->get_parameter("my_parameter").as_string();RCLCPP_INFO(this->get_logger(),"Hello %s!",my_param.c_str());std::vectorall_new_parameters{rclcpp::Parameter("my_parameter","world")};this->set_parameters(all_new_parameters);};timer_=this->create_wall_timer(1000ms,timer_callback);}private:rclcpp::TimerBase::SharedPtrtimer_;};intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +classMinimalParam:publicrclcpp::Node{public:MinimalParam():Node("minimal_param_node"){this->declare_parameter("my_parameter","world");autotimer_callback=[this](){std::stringmy_param=this->get_parameter("my_parameter").as_string();RCLCPP_INFO(this->get_logger(),"Hello %s!",my_param.c_str());std::vectorall_new_parameters{rclcpp::Parameter("my_parameter","world")};this->set_parameters(all_new_parameters);};timer_=this->create_wall_timer(1000ms,timer_callback);} + +Language: unknown +private:rclcpp::TimerBase::SharedPtrtimer_; + +Language: unknown +intmain(intargc,char**argv){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +// ...classMinimalParam:publicrclcpp::Node{public:MinimalParam():Node("minimal_param_node"){autoparam_desc=rcl_interfaces::msg::ParameterDescriptor{};param_desc.description="This parameter is mine!";this->declare_parameter("my_parameter","world",param_desc);autotimer_callback=[this](){std::stringmy_param=this->get_parameter("my_parameter").as_string();RCLCPP_INFO(this->get_logger(),"Hello %s!",my_param.c_str());std::vectorall_new_parameters{rclcpp::Parameter("my_parameter","world")};this->set_parameters(all_new_parameters);};timer_=this->create_wall_timer(1000ms,timer_callback);} + +Language: unknown +add_executable(minimal_param_nodesrc/cpp_parameters_node.cpp)ament_target_dependencies(minimal_param_noderclcpp)install(TARGETSminimal_param_nodeDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select cpp_parameters + +Language: unknown +colcon build --packages-select cpp_parameters + +Language: unknown +colcon build --merge-install --packages-select cpp_parameters + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run cpp_parameters minimal_param_node + +Language: unknown +[INFO] [minimal_param_node]: Hello world! + +Language: unknown +ros2 run cpp_parameters minimal_param_node + +Language: unknown +ros2 param list + +Language: unknown +ros2 param set /minimal_param_node my_parameter earth + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package="cpp_parameters",executable="minimal_param_node",name="custom_minimal_param_node",output="screen",emulate_tty=True,parameters=[{"my_parameter":"earth"}])]) + +Language: unknown +output="screen",emulate_tty=True, + +Language: unknown +install(DIRECTORY launchDESTINATION share/${PROJECT_NAME}) + +Language: unknown +colcon build --packages-select cpp_parameters + +Language: unknown +colcon build --packages-select cpp_parameters + +Language: unknown +colcon build --merge-install --packages-select cpp_parameters + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 launch cpp_parameters cpp_parameters_launch.py + +Language: unknown +[INFO] [custom_minimal_param_node]: Hello earth! diff --git "a/exported_docs/ros2/Using_parameters_in_a_class_(Python)\357\203\201.txt" "b/exported_docs/ros2/Using_parameters_in_a_class_(Python)\357\203\201.txt" new file mode 100644 index 0000000..f655b5f --- /dev/null +++ "b/exported_docs/ros2/Using_parameters_in_a_class_(Python)\357\203\201.txt" @@ -0,0 +1,125 @@ +Title: Using parameters in a class (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-Python.html +Section: Installation +-------------------------------------------------------------------------------- + +Using parameters in a class (Python)Goal:Create and run a class with ROS parameters using Python.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the Python node3 Build and runSummaryNext stepsBackgroundWhen making your ownnodesyou will sometimes need to add parameters that can be set from the launch file.This tutorial will show you how to create those parameters in a Python class, and how to set them in a launch file.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package. +You have also learned aboutparametersand their function in a ROS 2 system.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Followthese instructionsto create a new workspace namedros2_ws.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +Navigate intoros2_ws/srcand create a new package:ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameters --dependencies rclpyYour terminal will return a message verifying the creation of your packagepython_parametersand all its necessary files and folders.The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xmlorCMakeLists.txt.As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.PythonparametertutorialYourNameApache-2.02 Write the Python nodeInside theros2_ws/src/python_parameters/python_parametersdirectory, create a new file calledpython_parameters_node.pyand paste the following code within:importrclpyimportrclpy.nodeclassMinimalParam(rclpy.node.Node):def__init__(self):super().__init__('minimal_param_node')self.declare_parameter('my_parameter','world')self.timer=self.create_timer(1,self.timer_callback)deftimer_callback(self):my_param=self.get_parameter('my_parameter').get_parameter_value().string_valueself.get_logger().info('Hello%s!'%my_param)my_new_param=rclpy.parameter.Parameter('my_parameter',rclpy.Parameter.Type.STRING,'world')all_new_parameters=[my_new_param]self.set_parameters(all_new_parameters)defmain():rclpy.init()node=MinimalParam()rclpy.spin(node)if__name__=='__main__':main()2.1 Examine the codeTheimportstatements at the top are used to import the package dependencies.The next piece of code creates the class and the constructor. +The lineself.declare_parameter('my_parameter','world')of the constructor creates a parameter with the namemy_parameterand a default value ofworld. +The parameter type is inferred from the default value, so in this case it would be set to a string type. +Next thetimeris initialized with a period of 1, which causes thetimer_callbackfunction to be executed once a second.classMinimalParam(rclpy.node.Node):def__init__(self):super().__init__('minimal_param_node')self.declare_parameter('my_parameter','world')self.timer=self.create_timer(1,self.timer_callback)The first line of ourtimer_callbackfunction gets the parametermy_parameterfrom the node, and stores it inmy_param. +Next theget_loggerfunction ensures the event is logged. +Theset_parametersfunction then sets the parametermy_parameterback to the default string valueworld. +In the case that the user changed the parameter externally, this ensures it is always reset back to the original.deftimer_callback(self):my_param=self.get_parameter('my_parameter').get_parameter_value().string_valueself.get_logger().info('Hello%s!'%my_param)my_new_param=rclpy.parameter.Parameter('my_parameter',rclpy.Parameter.Type.STRING,'world')all_new_parameters=[my_new_param]self.set_parameters(all_new_parameters)Following thetimer_callbackis ourmain. +Here ROS 2 is initialized, an instance of theMinimalParamclass is constructed, andrclpy.spinstarts processing data from the node.defmain():rclpy.init()node=MinimalParam()rclpy.spin(node)if__name__=='__main__':main()2.1.1 (Optional) Add ParameterDescriptorOptionally, you can set a descriptor for the parameter. +Descriptors allow you to specify a text description of the parameter and its constraints, like making it read-only, specifying a range, etc. +For that to work, the__init__code has to be changed to:# ...classMinimalParam(rclpy.node.Node):def__init__(self):super().__init__('minimal_param_node')fromrcl_interfaces.msgimportParameterDescriptormy_parameter_descriptor=ParameterDescriptor(description='This parameter is mine!')self.declare_parameter('my_parameter','world',my_parameter_descriptor)self.timer=self.create_timer(1,self.timer_callback)The rest of the code remains the same. +Once you run the node, you can then runros2paramdescribe/minimal_param_nodemy_parameterto see the type and description.2.2 Add an entry pointOpen thesetup.pyfile. +Again, match themaintainer,maintainer_email,descriptionandlicensefields to yourpackage.xml:maintainer='YourName',maintainer_email='you@email.com',description='Python parameter tutorial',license='Apache-2.0',Add the following line within theconsole_scriptsbrackets of theentry_pointsfield:entry_points={'console_scripts':['minimal_param_node = python_parameters.python_parameters_node:main',],},Don’t forget to save.3 Build and runIt’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Navigate back to the root of your workspace,ros2_ws, and build your new package:LinuxmacOSWindowscolcon build --packages-select python_parameterscolcon build --packages-select python_parameterscolcon build --merge-install --packages-select python_parametersOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the node:ros2 run python_parameters minimal_param_nodeThe terminal should return the following message every second:[INFO] [parameter_node]: Hello world!Now you can see the default value of your parameter, but you want to be able to set it yourself. +There are two ways to accomplish this.3.1 Change via the consoleThis part will use the knowledge you have gained from thetutoral about parametersand apply it to the node you have just created.Make sure the node is running:ros2 run python_parameters minimal_param_nodeOpen another terminal, source the setup files from insideros2_wsagain, and enter the following line:ros2 param listThere you will see the custom parametermy_parameter. +To change it, simply run the following line in the console:ros2 param set /minimal_param_node my_parameter earthYou know it went well if you get the outputSetparametersuccessful. +If you look at the other terminal, you should see the output change to[INFO][minimal_param_node]:Helloearth!Since the node afterwards set the parameter back toworld, further outputs show[INFO][minimal_param_node]:Helloworld!3.2 Change via a launch fileYou can also set parameters in a launch file, but first you will need to add a launch directory. +Inside theros2_ws/src/python_parameters/directory, create a new directory calledlaunch. +In there, create a new file calledpython_parameters_launch.pyfromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='python_parameters',executable='minimal_param_node',name='custom_minimal_param_node',output='screen',emulate_tty=True,parameters=[{'my_parameter':'earth'}])])Here you can see that we setmy_parametertoearthwhen we launch our nodeparameter_node. +By adding the two lines below, we ensure our output is printed in our console.output="screen",emulate_tty=True,Now open thesetup.pyfile. +Add theimportstatements to the top of the file, and the other new statement to thedata_filesparameter to include all launch files:importosfromglobimportglob# ...setup(# ...data_files=[# ...(os.path.join('share',package_name),glob('launch/*launch.[pxy][yma]*')),])Open a console and navigate to the root of your workspace,ros2_ws, and build your new package:LinuxmacOSWindowscolcon build --packages-select python_parameterscolcon build --packages-select python_parameterscolcon build --merge-install --packages-select python_parametersThen source the setup files in a new terminal:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the node using the launch file we have just created:ros2 launch python_parameters python_parameters_launch.pyThe terminal should return the following message the first time:[INFO] [custom_minimal_param_node]: Hello earth!Further outputs should show[INFO][minimal_param_node]:Helloworld!every second.SummaryYou created a node with a custom parameter that can be set either from a launch file or the command line. +You added the dependencies, executables, and a launch file to the package configuration files so that you could build and run them, and see the parameter in action.Next stepsNow that you have some packages and ROS 2 systems of your own, thenext tutorialwill show you how to examine issues in your environment and systems in case you have problems. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameters --dependencies rclpy + +Language: unknown +PythonparametertutorialYourNameApache-2.0 + +Language: unknown +importrclpyimportrclpy.nodeclassMinimalParam(rclpy.node.Node):def__init__(self):super().__init__('minimal_param_node')self.declare_parameter('my_parameter','world')self.timer=self.create_timer(1,self.timer_callback)deftimer_callback(self):my_param=self.get_parameter('my_parameter').get_parameter_value().string_valueself.get_logger().info('Hello%s!'%my_param)my_new_param=rclpy.parameter.Parameter('my_parameter',rclpy.Parameter.Type.STRING,'world')all_new_parameters=[my_new_param]self.set_parameters(all_new_parameters)defmain():rclpy.init()node=MinimalParam()rclpy.spin(node)if__name__=='__main__':main() + +Language: unknown +classMinimalParam(rclpy.node.Node):def__init__(self):super().__init__('minimal_param_node')self.declare_parameter('my_parameter','world')self.timer=self.create_timer(1,self.timer_callback) + +Language: unknown +deftimer_callback(self):my_param=self.get_parameter('my_parameter').get_parameter_value().string_valueself.get_logger().info('Hello%s!'%my_param)my_new_param=rclpy.parameter.Parameter('my_parameter',rclpy.Parameter.Type.STRING,'world')all_new_parameters=[my_new_param]self.set_parameters(all_new_parameters) + +Language: unknown +defmain():rclpy.init()node=MinimalParam()rclpy.spin(node)if__name__=='__main__':main() + +Language: unknown +# ...classMinimalParam(rclpy.node.Node):def__init__(self):super().__init__('minimal_param_node')fromrcl_interfaces.msgimportParameterDescriptormy_parameter_descriptor=ParameterDescriptor(description='This parameter is mine!')self.declare_parameter('my_parameter','world',my_parameter_descriptor)self.timer=self.create_timer(1,self.timer_callback) + +Language: unknown +maintainer='YourName',maintainer_email='you@email.com',description='Python parameter tutorial',license='Apache-2.0', + +Language: unknown +entry_points={'console_scripts':['minimal_param_node = python_parameters.python_parameters_node:main',],}, + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select python_parameters + +Language: unknown +colcon build --packages-select python_parameters + +Language: unknown +colcon build --merge-install --packages-select python_parameters + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run python_parameters minimal_param_node + +Language: unknown +[INFO] [parameter_node]: Hello world! + +Language: unknown +ros2 run python_parameters minimal_param_node + +Language: unknown +ros2 param list + +Language: unknown +ros2 param set /minimal_param_node my_parameter earth + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='python_parameters',executable='minimal_param_node',name='custom_minimal_param_node',output='screen',emulate_tty=True,parameters=[{'my_parameter':'earth'}])]) + +Language: unknown +output="screen",emulate_tty=True, + +Language: unknown +importosfromglobimportglob# ...setup(# ...data_files=[# ...(os.path.join('share',package_name),glob('launch/*launch.[pxy][yma]*')),]) + +Language: unknown +colcon build --packages-select python_parameters + +Language: unknown +colcon build --packages-select python_parameters + +Language: unknown +colcon build --merge-install --packages-select python_parameters + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 launch python_parameters python_parameters_launch.py + +Language: unknown +[INFO] [custom_minimal_param_node]: Hello earth! diff --git "a/exported_docs/ros2/Using_theros2paramcommand-line_tool\357\203\201.txt" "b/exported_docs/ros2/Using_theros2paramcommand-line_tool\357\203\201.txt" new file mode 100644 index 0000000..f1a3373 --- /dev/null +++ "b/exported_docs/ros2/Using_theros2paramcommand-line_tool\357\203\201.txt" @@ -0,0 +1,55 @@ +Title: Using theros2paramcommand-line tool +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Using-ros2-param.html +Section: Installation +-------------------------------------------------------------------------------- + +Using theros2paramcommand-line toolTable of Contentsros2paramlistros2paramgetros2paramsetros2paramdeleteros2paramdescriberos2paramdumpros2paramloadParameters in ROS 2 can be get, set, listed, and described through a set of services as described inthe concept document. +Theros2paramcommand-line tool is a wrapper around these service calls that makes it easy to manipulate parameters from the command-line.ros2paramlistThis command will list all of the available parameters on a given node, or on all discoverable nodes if no node is given.To get all of the parameters on a given node:ros2 param list /my_nodeTo get all of the parameters on all nodes in the system (this can take a long time on a complicated network):ros2 param listros2paramgetThis command will get the value of a particular parameter on a particular node.To get the value of a parameter on a node:ros2 param get /my_node use_sim_timeros2paramsetThis command will set the value of a particular parameter on a particular node. +For most parameters, the type of the new value must be the same as the existing type.To set the value of a parameter on a node:ros2 param set /my_node use_sim_time falseThe value that is passed on the command-line is in YAML, which allows arbitrary YAML expressions to be used. +However, it also means that certain expressions will be interpreted differently than might be expected. +For instance, if the parametermy_stringon nodemy_nodeis of type string, the following will not work:ros2 param set /my_node my_string offThat’s because YAML is interpreting “off” as a boolean, andmy_stringis a string type. +This can be worked around by using the YAML syntax for explicitly setting strings, e.g.:ros param set /my_node my_string '!!str off'Additionally, YAML supports heterogeneous lists, containing (say) a string, a boolean, and an integer. +However, ROS 2 parameters do not support heterogenous lists, so any YAML list that has multiple types will be interpreted as a string. +Assuming that the parametermy_int_arrayon nodemy_nodeis of type integer array, the following will not work:ros param set /my_node my_int_array '[foo,off,1]'The following string typed parameter would work:ros param set /my_node my_string '[foo,off,1]'ros2paramdeleteThis command will remove a parameter from a particular node. +However, note that this can only remove dynamic parameters (not declared parameters). +Seethe concept documentfor more information.ros2 param delete /my_node my_stringros2paramdescribeThis command will provide a textual description of a particular parameter on a particular node:ros2 param describe /my_node use_sim_timeros2paramdumpThis command will print out all of the parameters on a particular node in a YAML file format. +The output of this command can then be used to re-run the node with the same parameters later:ros2 param dump /my_noderos2paramloadThis command will load the values of the parameters from a YAML file into a particular node. +That is, this command can reload values at runtime that were dumped out byros2paramdump:ros2 param load /my_node my_node.yaml + +Code Examples: + +Language: unknown +ros2 param list /my_node + +Language: unknown +ros2 param list + +Language: unknown +ros2 param get /my_node use_sim_time + +Language: unknown +ros2 param set /my_node use_sim_time false + +Language: unknown +ros2 param set /my_node my_string off + +Language: unknown +ros param set /my_node my_string '!!str off' + +Language: unknown +ros param set /my_node my_int_array '[foo,off,1]' + +Language: unknown +ros param set /my_node my_string '[foo,off,1]' + +Language: unknown +ros2 param delete /my_node my_string + +Language: unknown +ros2 param describe /my_node use_sim_time + +Language: unknown +ros2 param dump /my_node + +Language: unknown +ros2 param load /my_node my_node.yaml diff --git "a/exported_docs/ros2/Using_time_(C++)\357\203\201.txt" "b/exported_docs/ros2/Using_time_(C++)\357\203\201.txt" new file mode 100644 index 0000000..c26af31 --- /dev/null +++ "b/exported_docs/ros2/Using_time_(C++)\357\203\201.txt" @@ -0,0 +1,41 @@ +Title: Using time (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Learning-About-Tf2-And-Time-Cpp.html +Section: Installation +-------------------------------------------------------------------------------- + +Using time (C++)Goal:Learn how to get a transform at a specific time and wait for a transform to be available on the tf2 tree usinglookupTransform()function.Tutorial level:IntermediateTime:10 minutesContentsBackgroundTasks1 Update the listener node2 Fix the listener node3 Check the resultsSummaryBackgroundIn previous tutorials, we recreated the turtle demo by writing atf2 broadcasterand atf2 listener. +We also learned how toadd a new frame to the transformation treeand learned how tf2 keeps track of a tree of coordinate frames. +This tree changes over time, and tf2 stores a time snapshot for every transform (for up to 10 seconds by default). +Until now we used thelookupTransform()function to get access to the latest available transforms in that tf2 tree, without knowing at what time that transform was recorded. +This tutorial will teach you how to get a transform at a specific time.Tasks1 Update the listener nodeLet’s go back to where we ended in theadding a frame tutorial. +Go to thelearning_tf2_cpppackage. +Openturtle_tf2_listener.cppand take a look at thelookupTransform()call:try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,tf2::TimePointZero);}catch(consttf2::TransformException&ex){You can see that we specified a time equal to 0 by callingtf2::TimePointZero.NoteThetf2package has it’s own time typetf2::TimePoint, which is different fromrclcpp::Time. +Many APIs in the packagetf2_rosautomatically convert betweenrclcpp::Timeandtf2::TimePoint.rclcpp::Time(0,0,this->get_clock()->get_clock_type())could have been used here, but it would have been converted totf2::TimePointZeroanyways.For tf2, time 0 means “the latest available” transform in the buffer. +Now, change this line to get the transform at the current time,this->get_clock()->now():rclcpp::Timenow=this->get_clock()->now();try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,now);}catch(consttf2::TransformException&ex){Now build the package and try to run the launch file.ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.pyYou will notice that it fails and outputs something similar to this:[INFO] [1629873136.345688064] [listener]: Could not transform turtle2 to turtle1: Lookup wouldrequire extrapolation into the future. Requested time 1629873136.345539 but the latest datais at time 1629873136.338804, when looking up transform from frame [turtle1] to frame [turtle2]It tells you that the frame does not exist or that the data is in the future.To understand why is this happening we need to understand how buffers work. +Firstly, each listener has a buffer where it stores all the coordinate transforms coming from the different tf2 broadcasters. +Secondly, when a broadcaster sends out a transform, it takes some time before that transform gets into the buffer (usually a couple of milliseconds). +As a result, when you request a frame transform at time “now”, you should wait a few milliseconds for that information to arrive.2 Fix the listener nodetf2 provides a nice tool that will wait until a transform becomes available. +You use this by adding a timeout parameter tolookupTransform(). +To fix this, edit your code as shown below (add the last timeout parameter):rclcpp::Timenow=this->get_clock()->now();try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,now,50ms);}catch(consttf2::TransformException&ex){ThelookupTransform()can take four arguments, where the last one is an optional timeout. +It will block for up to that duration waiting for it to timeout.3 Check the resultsYou can now build the package and run the launch file.ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.pyYou should notice thatlookupTransform()will actually block until the transform between the two turtles becomes available (this will usually take a few milliseconds). +Once the timeout has been reached (fifty milliseconds in this case), an exception will be raised only if the transform is still not available.SummaryIn this tutorial, you learned how to acquire a transform at a specific timestamp and how to wait for a transform to be available on the tf2 tree when using thelookupTransform()function. + +Code Examples: + +Language: unknown +try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,tf2::TimePointZero);}catch(consttf2::TransformException&ex){ + +Language: unknown +rclcpp::Timenow=this->get_clock()->now();try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,now);}catch(consttf2::TransformException&ex){ + +Language: unknown +ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.py + +Language: unknown +[INFO] [1629873136.345688064] [listener]: Could not transform turtle2 to turtle1: Lookup wouldrequire extrapolation into the future. Requested time 1629873136.345539 but the latest datais at time 1629873136.338804, when looking up transform from frame [turtle1] to frame [turtle2] + +Language: unknown +rclcpp::Timenow=this->get_clock()->now();try{t=tf_buffer_->lookupTransform(toFrameRel,fromFrameRel,now,50ms);}catch(consttf2::TransformException&ex){ + +Language: unknown +ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.py diff --git "a/exported_docs/ros2/Using_variants\357\203\201.txt" "b/exported_docs/ros2/Using_variants\357\203\201.txt" new file mode 100644 index 0000000..0e648d6 --- /dev/null +++ "b/exported_docs/ros2/Using_variants\357\203\201.txt" @@ -0,0 +1,20 @@ +Title: Using variants +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Using-Variants.html +Section: Installation +-------------------------------------------------------------------------------- + +Using variantsMetapackages do not provide software directly but depend on a group of other related packages to provide a convienent installation mechanism for the complete group of packages.[1][2]Variants are a list of official metapackages for commonly useful groups of ROS packages.[1]https://wiki.debian.org/metapackage[2]https://help.ubuntu.com/community/MetaPackagesThe different variants in ROS 2 are specified inREP-2001.In addition to the official variants, there may be metapackages for specific institutions or robots as described inREP-108.Adding variantsAdditional variants that are of general use to the ROS community can be proposed by contributing an update toREP-2001 via pull requestdescribing the packages included in the new variant. +Institution and robot specific variants can be published directly by their respective maintainers and no update to REP-2001 is required.Creating project-specific variantsIf you are creating ROS packages to use privately in your own projects, you can create variants specific to your projects using the official variants as examples. +To do so you need only create two files:A minimal variant package is created as a package with theament_cmakebuild type, abuildtool_dependonament_cmakeandexec_dependentries for each package you want to include in the variant.my_project_variant1.0.0Apackagetoaggregateallpackagesinmy_project.MaintainerNameApache-2.0my_project_msgsmy_project_servicesmy_project_examplesament_cmake
A minimal ament_cmake package includes aCMakeLists.txtwhich registers the package.xml as an ament package for use in ROS 2.cmake_minimum_required(VERSION3.5)project(my_project_variantNONE)find_package(ament_cmakeREQUIRED)ament_package()You can then build and install your variant package alongside your other private packages.Creating custom variants with platform-specific toolsSome platforms have tools for creating basic packages that do not require a full ROS build farm environment or equivalent infrastructure. +It is possible to use these tools to create platform-dependent variants. +This approach does not include support for ROS packaging tools and is platform dependent but requires much less infrastructure to produce if you are creating collections of existing packages rather than a mix of public and private ROS packages. +For example, on Debian or Ubuntu systems you can use theequivsutilities. +The Debian Administrator’s handbook has aSection on meta-packages. + +Code Examples: + +Language: unknown +my_project_variant1.0.0Apackagetoaggregateallpackagesinmy_project.MaintainerNameApache-2.0my_project_msgsmy_project_servicesmy_project_examplesament_cmake
+ +Language: unknown +cmake_minimum_required(VERSION3.5)project(my_project_variantNONE)find_package(ament_cmakeREQUIRED)ament_package() diff --git "a/exported_docs/ros2/Usingcolconto_build_packages\357\203\201.txt" "b/exported_docs/ros2/Usingcolconto_build_packages\357\203\201.txt" new file mode 100644 index 0000000..e208c4c --- /dev/null +++ "b/exported_docs/ros2/Usingcolconto_build_packages\357\203\201.txt" @@ -0,0 +1,117 @@ +Title: Usingcolconto build packages +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html +Section: Installation +-------------------------------------------------------------------------------- + +Usingcolconto build packagesTable of ContentsBackgroundPrerequisitesInstall colconInstall ROS 2BasicsCreate a workspaceAdd some sourcesSource an underlayBuild the workspaceRun testsSource the environmentTry a demoCreate your own packageSetupcolcon_cdSetupcolcontab completionTipsGoal:Build a ROS 2 workspace withcolcon.Tutorial level:BeginnerTime:20 minutesThis is a brief tutorial on how to create and build a ROS 2 workspace withcolcon. +It is a practical tutorial and not designed to replace the core documentation.Backgroundcolconis an iteration on the ROS build toolscatkin_make,catkin_make_isolated,catkin_toolsandament_tools. +For more information on the design of colcon seethis document.The source code can be found in thecolcon GitHub organization.PrerequisitesInstall colconLinuxmacOSWindowssudoaptinstallpython3-colcon-common-extensionspython3-mpipinstallcolcon-common-extensionspipinstall-Ucolcon-common-extensionsInstall ROS 2To build the samples, you will need to install ROS 2.Follow theinstallation instructions.AttentionIf installing from deb packages, this tutorial requires thedesktop installation.BasicsA ROS workspace is a directory with a particular structure. +Commonly there is asrcsubdirectory. +Inside that subdirectory is where the source code of ROS packages will be located. +Typically the directory starts otherwise empty.colcon does out of source builds. +By default it will create the following directories as peers of thesrcdirectory:Thebuilddirectory will be where intermediate files are stored. +For each package a subfolder will be created in which e.g. CMake is being invoked.Theinstalldirectory is where each package will be installed to. +By default each package will be installed into a separate subdirectory.Thelogdirectory contains various logging information about each colcon invocation.NoteCompared to catkin there is nodeveldirectory.Create a workspaceFirst, create a directory (ros2_ws) to contain our workspace:LinuxmacOSWindowsmkdir-p~/ros2_ws/srccd~/ros2_wsmkdir-p~/ros2_ws/srccd~/ros2_wsmd\dev\ros2_ws\srccd\dev\ros2_wsAt this point the workspace contains a single empty directorysrc:. +└──src1directory,0filesAdd some sourcesLet’s clone theexamplesrepository into thesrcdirectory of the workspace:gitclonehttps://github.com/ros2/examplessrc/examples-bjazzyNow the workspace should have the source code to the ROS 2 examples:. +└──src└──examples├──CONTRIBUTING.md├──LICENSE├──rclcpp├──rclpy└──README.md4directories,3filesSource an underlayIt is important that we have sourced the environment for an existing ROS 2 installation that will provide our workspace with the necessary build dependencies for the example packages. +This is achieved by sourcing the setup script provided by a binary installation or a source installation, ie. another colcon workspace (seeInstallation). +We call this environment anunderlay.Our workspace,ros2_ws, will be anoverlayon top of the existing ROS 2 installation. +In general, it is recommended to use an overlay when you plan to iterate on a small number of packages, rather than putting all of your packages into the same workspace.Build the workspaceAttentionTo build packages on Windows you need to be in a Visual Studio environment, seeBuilding the ROS 2 Codefor more details.In the root of the workspace, runcolconbuild. +Since build types such asament_cmakedo not support the concept of thedevelspace and require the package to be installed, colcon supports the option--symlink-install. +This allows the installed files to be changed by changing the files in thesourcespace (e.g. Python files or other non-compiled resources) for faster iteration.LinuxmacOSWindowscolcon build --symlink-installcolcon build --symlink-installcolcon build --symlink-install --merge-installWindows doesn’t allow long paths, somerge-installwill combine all the paths into theinstalldirectory.After the build is finished, we should see thebuild,install, andlogdirectories:. +├──build +├──install +├──log +└──src4directories,0filesRun testsTo run tests for the packages we just built, run the following:LinuxmacOSWindowscolcon testcolcon testRemember to use ax64NativeToolsCommandPromptforVS2019for executing the following command, as we are going to build a workspace.colcon test --merge-installYou also need to specify--merge-installhere since we used it for building above.Source the environmentWhen colcon has completed building successfully, the output will be in theinstalldirectory. +Before you can use any of the installed executables or libraries, you will need to add them to your path and library paths. +colcon will have generated bash/bat files in theinstalldirectory to help set up the environment. +These files will add all of the required elements to your path and library paths as well as provide any bash or shell commands exported by packages.LinuxmacOSWindowssourceinstall/setup.bash.install/setup.bashcallinstall\setup.batOr with Powershell:install\setup.ps1Try a demoWith the environment sourced, we can run executables built by colcon. +Let’s run a subscriber node from the examples:ros2runexamples_rclcpp_minimal_subscribersubscriber_member_functionIn another terminal, let’s run a publisher node (don’t forget to source the setup script):ros2runexamples_rclcpp_minimal_publisherpublisher_member_functionYou should see messages from the publisher and subscriber with numbers incrementing.Create your own packagecolcon uses thepackage.xmlspecification defined inREP 149(format 2is also supported).colcon supports multiple build types. +The recommended build types areament_cmakeandament_python. +Also supported are purecmakepackages.An example of anament_pythonbuild is theament_index_python package, where the setup.py is the primary entry point for building.A package such asdemo_nodes_cppuses theament_cmakebuild type, and uses CMake as the build tool.For convenience, you can use the toolros2pkgcreateto create a new package based on a template.NoteForcatkinusers, this is the equivalent ofcatkin_create_package.Setupcolcon_cdThe commandcolcon_cdallows you to quickly change the current working directory of your shell to the directory of a package. +As an examplecolcon_cdsome_ros_packagewould quickly bring you to the directory~/ros2_ws/src/some_ros_package.LinuxmacOSWindowsecho "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=/opt/ros/jazzy/" >> ~/.bashrcecho "source /usr/local/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=~/ros2_install" >> ~/.bashrcNot yet availableDepending on the way you installedcolcon_cdand where your workspace is, the instructions above may vary, please refer tothe documentationfor more details. +To undo this in Linux and macOS, locate your system’s shell startup script and remove the appended source and export commands.Setupcolcontab completionThecolconcommand supports command completion for bash and bash-like shells. +Thecolcon-argcompletepackage must be installed, andsome setup may be requiredto make it work.TipsIf you do not want to build a specific package place an empty file namedCOLCON_IGNOREin the directory and it will not be indexed.If you want to avoid configuring and building tests in CMake packages you can pass:--cmake-args-DBUILD_TESTING=0.If you want to run a single particular test from a package:colcontest--packages-selectYOUR_PKG_NAME--ctest-args-RYOUR_TEST_IN_PKG + +Code Examples: + +Language: unknown +sudoaptinstallpython3-colcon-common-extensions + +Language: unknown +python3-mpipinstallcolcon-common-extensions + +Language: unknown +pipinstall-Ucolcon-common-extensions + +Language: unknown +mkdir-p~/ros2_ws/srccd~/ros2_ws + +Language: unknown +mkdir-p~/ros2_ws/srccd~/ros2_ws + +Language: unknown +md\dev\ros2_ws\srccd\dev\ros2_ws + +Language: unknown +. +└──src1directory,0files + +Language: unknown +gitclonehttps://github.com/ros2/examplessrc/examples-bjazzy + +Language: unknown +. +└──src└──examples├──CONTRIBUTING.md├──LICENSE├──rclcpp├──rclpy└──README.md4directories,3files + +Language: unknown +colcon build --symlink-install + +Language: unknown +colcon build --symlink-install + +Language: unknown +colcon build --symlink-install --merge-install + +Language: unknown +. +├──build +├──install +├──log +└──src4directories,0files + +Language: unknown +colcon test + +Language: unknown +colcon test + +Language: unknown +colcon test --merge-install + +Language: unknown +sourceinstall/setup.bash + +Language: unknown +.install/setup.bash + +Language: unknown +callinstall\setup.bat + +Language: unknown +install\setup.ps1 + +Language: unknown +ros2runexamples_rclcpp_minimal_subscribersubscriber_member_function + +Language: unknown +ros2runexamples_rclcpp_minimal_publisherpublisher_member_function + +Language: unknown +echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=/opt/ros/jazzy/" >> ~/.bashrc + +Language: unknown +echo "source /usr/local/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrcecho "export _colcon_cd_root=~/ros2_install" >> ~/.bashrc + +Language: unknown +colcontest--packages-selectYOUR_PKG_NAME--ctest-args-RYOUR_TEST_IN_PKG diff --git "a/exported_docs/ros2/Usingros2doctorto_identify_issues\357\203\201.txt" "b/exported_docs/ros2/Usingros2doctorto_identify_issues\357\203\201.txt" new file mode 100644 index 0000000..3f0bade --- /dev/null +++ "b/exported_docs/ros2/Usingros2doctorto_identify_issues\357\203\201.txt" @@ -0,0 +1,63 @@ +Title: Usingros2doctorto identify issues +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Getting-Started-With-Ros2doctor.html +Section: Installation +-------------------------------------------------------------------------------- + +Usingros2doctorto identify issuesGoal:Identify issues in your ROS 2 setup using theros2doctortool.Tutorial level:BeginnerTime:10 minutesContentsBackgroundPrerequisitesTasks1 Check your setup2 Check a system3 Get a full reportSummaryRelated contentNext stepsBackgroundWhen your ROS 2 setup is not running as expected, you can check its settings with theros2doctortool.ros2doctorchecks all aspects of ROS 2, including platform, version, network, environment, running systems and more, and warns you about possible errors and reasons for issues.Prerequisitesros2doctoris part of theros2clipackage. +As long as you haveros2cliinstalled (which any normal install should have), you will be able to useros2doctor.This tutorial usesturtlesimto illustrate some of the examples.Tasks1 Check your setupLet’s examine your general ROS 2 setup as a whole withros2doctor. +First, source ROS 2 in a new terminal, then enter the command:ros2 doctorThis will conduct checks over all your setup modules and return warnings and errors.If your ROS 2 setup is in perfect shape, you’ll see a message similar to this:All checks passedHowever, it’s not unusual to have a few warnings returned. +AUserWarningdoesn’t mean your setup is unusable; it’s more likely just an indication that something is configured in a way that’s not ideal.If you do receive a warning, it will look something like this:: : UserWarning: For example,ros2doctorwill find this warning if you’re using an unstable ROS 2 distribution:UserWarning: Distribution is not fully supported or tested. To get more consistent features, download a stable version at https://index.ros.org/doc/ros2/Installation/Ifros2doctoronly finds warnings in your system, you will still receive theAllcheckspassedmessage.Most checks are categorized as warnings as opposed to errors. +It’s mostly up to you, the user, to determine the importance of the feedbackros2doctorreturns. +If it does find a rare error in your setup, indicated byUserWarning:ERROR:, the check is considered failed.You will see a message similar to the following list of issue feedback:1/3 checks failedFailed modules: networkAn error indicates the system is missing important settings or functions that are crucial to ROS 2. +Errors should be addressed to ensure the system functions properly.2 Check a systemYou can also examine a running ROS 2 system to identify possible causes for issues. +To seeros2doctorworking on a running system, let’s run turtlesim, which has nodes actively communicating with each other.Start up the system by opening a new terminal, sourcing ROS 2, and entering the command:ros2 run turtlesim turtlesim_nodeOpen another terminal and source ROS 2 to run the teleop controls:ros2 run turtlesim turtle_teleop_keyNow runros2doctoragain in its own terminal. +You will see the warnings and errors you had the last time you ranros2doctoron your setup if you had any. +Following those will be a couple new warnings relating to the system itself:UserWarning: Publisher without subscriber detected on /turtle1/color_sensor.UserWarning: Publisher without subscriber detected on /turtle1/pose.It seems that the/turtlesimnode publishes data to two topics that aren’t being subscribed to, andros2doctorthinks this could possibly lead to issues.If you run commands to echo the/color_sensorand/posetopics, those warnings will disappear because the publishers will have subscribers.You can try this by opening two new terminals while turtlesim is still running, sourcing ROS 2 in each, and running each of the following commands in their own terminal:ros2 topic echo /turtle1/color_sensorros2 topic echo /turtle1/poseThen runros2doctorin its terminal again. +Thepublisherwithoutsubscriberwarnings will be gone. +(Make sure to enterCtrl+Cin the terminals where you ranecho).Now try exiting either the turtlesim window or quitting the teleop and runningros2doctoragain. +You’ll see more warnings indicatingpublisherwithoutsubscriberorsubscriberwithoutpublisherfor different topics, now that one node in the system isn’t available.In a complex system with many nodes,ros2doctorwould be invaluable for identifying possible reasons for communication issues.3 Get a full reportWhileros2doctorwill let you know warnings about your network, system, etc., running it with the--reportargument will give you much more detail to help you analyze issues.You might want to use--reportif you get a warning about your network setup and want to find out exactly what part of your configuration is causing the warning.It’s also very helpful when you need to open a support ticket to get help with ROS 2. +You can copy and paste the relevant parts of your report into the ticket so the people helping you can better understand your environment and provide better assistance.To get a full report, enter the following command in the terminal:ros2 doctor --reportWhich will return a list of information categorized into five groups:NETWORK CONFIGURATION...PLATFORM INFORMATION...RMW MIDDLEWARE...ROS 2 INFORMATION...TOPIC LIST...You can crosscheck the information here against the warnings you get when runningros2doctor. +For example, ifros2doctorreturned the warning (mentioned earlier) that your distribution is “not fully supported or tested”, you might take a look at theROS2INFORMATIONsection of the report:distribution name : distribution type : ros2distribution status : prereleaserelease platforms : {'': ['']}Here you can see thedistributionstatusisprerelease, which explains why it’s not fully supported.Summaryros2doctorwill inform you of problems in your ROS 2 setup and running systems. +You can get a deeper look at information behind those warnings by using the--reportargument.Keep in mind,ros2doctoris not a debug tool; it won’t help with errors in your code or on the implementation side of your system.Related contentros2doctor’s READMEwill tell you more about different arguments. +You might want to take a look around theros2doctorrepo as well, since it’s fairly beginner friendly and a great place to get started with contributing.Next stepsYou’ve completed the beginner level tutorials! + +Code Examples: + +Language: unknown +ros2 doctor + +Language: unknown +All checks passed + +Language: unknown +: : UserWarning: + +Language: unknown +UserWarning: Distribution is not fully supported or tested. To get more consistent features, download a stable version at https://index.ros.org/doc/ros2/Installation/ + +Language: unknown +1/3 checks failedFailed modules: network + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +UserWarning: Publisher without subscriber detected on /turtle1/color_sensor.UserWarning: Publisher without subscriber detected on /turtle1/pose. + +Language: unknown +ros2 topic echo /turtle1/color_sensor + +Language: unknown +ros2 topic echo /turtle1/pose + +Language: unknown +ros2 doctor --report + +Language: unknown +NETWORK CONFIGURATION...PLATFORM INFORMATION...RMW MIDDLEWARE...ROS 2 INFORMATION...TOPIC LIST... + +Language: unknown +distribution name : distribution type : ros2distribution status : prereleaserelease platforms : {'': ['']} diff --git "a/exported_docs/ros2/Usingrqt_consoleto_view_logs\357\203\201.txt" "b/exported_docs/ros2/Usingrqt_consoleto_view_logs\357\203\201.txt" new file mode 100644 index 0000000..fc33617 --- /dev/null +++ "b/exported_docs/ros2/Usingrqt_consoleto_view_logs\357\203\201.txt" @@ -0,0 +1,35 @@ +Title: Usingrqt_consoleto view logs +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Using-Rqt-Console/Using-Rqt-Console.html +Section: Installation +-------------------------------------------------------------------------------- + +Usingrqt_consoleto view logsGoal:Get to knowrqt_console, a tool for introspecting log messages.Tutorial level:BeginnerTime:5 minutesContentsBackgroundPrerequisitesTasks1 Setup2 Messages on rqt_console3 Logger levelsSummaryNext stepsBackgroundrqt_consoleis a GUI tool used to introspect log messages in ROS 2. +Typically, log messages show up in your terminal. +Withrqt_console, you can collect those messages over time, view them closely and in a more organized manner, filter them, save them and even reload the saved files to introspect at a different time.Nodes use logs to output messages concerning events and status in a variety of ways. +Their content is usually informational, for the sake of the user.PrerequisitesYou will needrqt_console and turtlesiminstalled.As always, don’t forget to source ROS 2 inevery new terminal you open.Tasks1 SetupStartrqt_consolein a new terminal with the following command:ros2 run rqt_console rqt_consoleTherqt_consolewindow will open:The first section of the console is where log messages from your system will display.In the middle you have the option to filter messages by excluding severity levels. +You can also add more exclusion filters using the plus-sign button to the right.The bottom section is for highlighting messages that include a string you input. +You can add more filters to this section as well.Now startturtlesimin a new terminal with the following command:ros2 run turtlesim turtlesim_node2 Messages on rqt_consoleTo produce log messages forrqt_consoleto display, let’s have the turtle run into the wall. +In a new terminal, enter theros2topicpubcommand (discussed in detail in thetopics tutorial) below:ros2 topic pub -r 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0,y: 0.0,z: 0.0}}"Since the above command is publishing the topic at a steady rate, the turtle is continuously running into the wall. +Inrqt_consoleyou will see the same message with theWarnseverity level displayed over and over, like so:PressCtrl+Cin the terminal where you ran theros2topicpubcommand to stop your turtle from running into the wall.3 Logger levelsROS 2’s logger levels are ordered by severity:FatalErrorWarnInfoDebugThere is no exact standard for what each level indicates, but it’s safe to assume that:Fatalmessages indicate the system is going to terminate to try to protect itself from detriment.Errormessages indicate significant issues that won’t necessarily damage the system, but are preventing it from functioning properly.Warnmessages indicate unexpected activity or non-ideal results that might represent a deeper issue, but don’t harm functionality outright.Infomessages indicate event and status updates that serve as a visual verification that the system is running as expected.Debugmessages detail the entire step-by-step process of the system execution.The default level isInfo. +You will only see messages of the default severity level and more-severe levels.Normally, onlyDebugmessages are hidden because they’re the only level less severe thanInfo. +For example, if you set the default level toWarn, you would only see messages of severityWarn,Error, andFatal.3.1 Set the default logger levelYou can set the default logger level when you first run the/turtlesimnode using remapping. +Enter the following command in your terminal:ros2 run turtlesim turtlesim_node --ros-args --log-level WARNNow you won’t see the initialInfolevel messages that came up in the console last time you startedturtlesim. +That’s becauseInfomessages are lower priority than the new default severity,Warn.Summaryrqt_consolecan be very helpful if you need to closely examine the log messages from your system. +You might want to examine log messages for any number of reasons, usually to find out where something went wrong and the series of events leading up to that.Next stepsThe next tutorial will teach you about starting multiple nodes at once withROS 2 Launch. + +Code Examples: + +Language: unknown +ros2 run rqt_console rqt_console + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +ros2 topic pub -r 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0,y: 0.0,z: 0.0}}" + +Language: unknown +FatalErrorWarnInfoDebug + +Language: unknown +ros2 run turtlesim turtlesim_node --ros-args --log-level WARN diff --git "a/exported_docs/ros2/Usingturtlesim,ros2,_andrqt\357\203\201.txt" "b/exported_docs/ros2/Usingturtlesim,ros2,_andrqt\357\203\201.txt" new file mode 100644 index 0000000..17e819a --- /dev/null +++ "b/exported_docs/ros2/Usingturtlesim,ros2,_andrqt\357\203\201.txt" @@ -0,0 +1,62 @@ +Title: Usingturtlesim,ros2, andrqt +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Introducing-Turtlesim/Introducing-Turtlesim.html +Section: Installation +-------------------------------------------------------------------------------- + +Usingturtlesim,ros2, andrqtGoal:Install and use the turtlesim package and rqt tools to prepare for upcoming tutorials.Tutorial level:BeginnerTime:15 minutesContentsBackgroundPrerequisitesTasks1 Install turtlesim2 Start turtlesim3 Use turtlesim4 Install rqt5 Use rqt6 Remapping7 Close turtlesimSummaryNext stepsRelated contentBackgroundTurtlesim is a lightweight simulator for learning ROS 2. +It illustrates what ROS 2 does at the most basic level to give you an idea of what you will do with a real robot or a robot simulation later on.The ros2 tool is how the user manages, introspects, and interacts with a ROS system. +It supports multiple commands that target different aspects of the system and its operation. +One might use it to start a node, set a parameter, listen to a topic, and many more. +The ros2 tool is part of the core ROS 2 installation.rqt is a graphical user interface (GUI) tool for ROS 2. +Everything done in rqt can be done on the command line, but rqt provides a more user-friendly way to manipulate ROS 2 elements.This tutorial touches upon core ROS 2 concepts, like nodes, topics, and services. +All of these concepts will be elaborated on in later tutorials; for now, you will simply set up the tools and get a feel for them.PrerequisitesThe previous tutorial,Configuring environment, will show you how to set up your environment.Tasks1 Install turtlesimAs always, start by sourcing your setup files in a new terminal, as described in theprevious tutorial.Install the turtlesim package for your ROS 2 distro:LinuxmacOSWindowssudo apt updatesudo apt install ros-jazzy-turtlesimAs long as the archive you installed ROS 2 from contains theros_tutorialsrepository, you should already have turtlesim installed.As long as the archive you installed ROS 2 from contains theros_tutorialsrepository, you should already have turtlesim installed.Check that the package is installed:ros2 pkg executables turtlesimThe above command should return a list of turtlesim’s executables:turtlesim draw_squareturtlesim mimicturtlesim turtle_teleop_keyturtlesim turtlesim_node2 Start turtlesimTo start turtlesim, enter the following command in your terminal:ros2 run turtlesim turtlesim_nodeThe simulator window should appear, with a random turtle in the center.In the terminal, under the command, you will see messages from the node:[INFO] [turtlesim]: Starting turtlesim with node name /turtlesim[INFO] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]There you can see the default turtle’s name and the coordinates where it spawns.3 Use turtlesimOpen a new terminal and source ROS 2 again.Now you will run a new node to control the turtle in the first node:ros2 run turtlesim turtle_teleop_keyAt this point you should have three windows open: a terminal runningturtlesim_node, a terminal runningturtle_teleop_keyand the turtlesim window. +Arrange these windows so that you can see the turtlesim window, but also have the terminal runningturtle_teleop_keyactive so that you can control the turtle in turtlesim.Use the arrow keys on your keyboard to control the turtle. +It will move around the screen, using its attached “pen” to draw the path it followed so far.NotePressing an arrow key will only cause the turtle to move a short distance and then stop. +This is because, realistically, you wouldn’t want a robot to continue carrying on an instruction if, for example, the operator lost the connection to the robot.You can see the nodes, and their associated topics, services, and actions, using thelistsubcommands of the respective commands:ros2 node listros2 topic listros2 service listros2 action listYou will learn more about these concepts in the coming tutorials. +Since the goal of this tutorial is only to get a general overview of turtlesim, you will use rqt to call some of the turtlesim services and interact withturtlesim_node.4 Install rqtOpen a new terminal to installrqtand its plugins:UbuntuRHELmacOSWindowssudo apt updatesudo apt install '~nros-jazzy-rqt*'sudo dnf install 'ros-jazzy-rqt*'The standard archive for installing ROS 2 on macOS containsrqtand its plugins, so you should already haverqtinstalled.The standard archive for installing ROS 2 on Windows containsrqtand its plugins, so you should already haverqtinstalled.To run rqt:rqt5 Use rqtWhen running rqt for the first time, the window will be blank. +No worries; just selectPlugins>Services>Service Callerfrom the menu bar at the top.NoteIt may take some time for rqt to locate all the plugins. +If you click onPluginsbut don’t seeServicesor any other options, you should close rqt and enter the commandrqt--force-discoverin your terminal.Use the refresh button to the left of theServicedropdown list to ensure all the services of your turtlesim node are available.Click on theServicedropdown list to see turtlesim’s services, and select the/spawnservice.5.1 Try the spawn serviceLet’s use rqt to call the/spawnservice. +You can guess from its name that/spawnwill create another turtle in the turtlesim window.Give the new turtle a unique name, liketurtle2, by double-clicking between the empty single quotes in theExpressioncolumn. +You can see that this expression corresponds to the value ofnameand is of typestring.Next enter some valid coordinates at which to spawn the new turtle, likex=1.0andy=1.0.NoteIf you try to spawn a new turtle with the same name as an existing turtle, like the defaultturtle1, you will get an error message in the terminal runningturtlesim_node:[ERROR] [turtlesim]: A turtle named [turtle1] already existsTo spawnturtle2, you then need to call the service by clicking theCallbutton on the upper right side of the rqt window.If the service call was successful, you should see a new turtle (again with a random design) spawn at the coordinates you input forxandy.If you refresh the service list in rqt, you will also see that now there are services related to the new turtle,/turtle2/..., in addition to/turtle1/....5.2 Try the set_pen serviceNow let’s giveturtle1a unique pen using the/set_penservice:The values forr,gandb, which are between 0 and 255, set the color of the penturtle1draws with, andwidthsets the thickness of the line.To haveturtle1draw with a distinct red line, change the value ofrto 255, and the value ofwidthto 5. +Don’t forget to call the service after updating the values.If you return to the terminal whereturtle_teleop_keyis running and press the arrow keys, you will seeturtle1’s pen has changed.You’ve probably also noticed that there’s no way to moveturtle2. +That’s because there is no teleop node forturtle2.6 RemappingYou need a second teleop node in order to controlturtle2. +However, if you try to run the same command as before, you will notice that this one also controlsturtle1. +The way to change this behavior is by remapping thecmd_veltopic.In a new terminal, source ROS 2, and run:ros2 run turtlesim turtle_teleop_key --ros-args --remap turtle1/cmd_vel:=turtle2/cmd_velNow, you can moveturtle2when this terminal is active, andturtle1when the other terminal runningturtle_teleop_keyis active.7 Close turtlesimTo stop the simulation, you can enterCtrl+Cin theturtlesim_nodeterminal, andqin theturtle_teleop_keyterminals.SummaryUsing turtlesim and rqt is a great way to learn the core concepts of ROS 2.Next stepsNow that you have turtlesim and rqt up and running, and an idea of how they work, let’s dive into the first core ROS 2 concept with the next tutorial,Understanding nodes.Related contentThe turtlesim package can be found in theros_tutorialsrepo.This community contributed videodemonstrates many of the items covered in this tutorial. + +Code Examples: + +Language: unknown +sudo apt updatesudo apt install ros-jazzy-turtlesim + +Language: unknown +ros2 pkg executables turtlesim + +Language: unknown +turtlesim draw_squareturtlesim mimicturtlesim turtle_teleop_keyturtlesim turtlesim_node + +Language: unknown +ros2 run turtlesim turtlesim_node + +Language: unknown +[INFO] [turtlesim]: Starting turtlesim with node name /turtlesim[INFO] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000] + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +ros2 node listros2 topic listros2 service listros2 action list + +Language: unknown +sudo apt updatesudo apt install '~nros-jazzy-rqt*' + +Language: unknown +sudo dnf install 'ros-jazzy-rqt*' + +Language: unknown +rqt + +Language: unknown +[ERROR] [turtlesim]: A turtle named [turtle1] already exists + +Language: unknown +ros2 run turtlesim turtle_teleop_key --ros-args --remap turtle1/cmd_vel:=turtle2/cmd_vel diff --git "a/exported_docs/ros2/Visualizing_ROS_2_data_with_Foxglove_Studio\357\203\201.txt" "b/exported_docs/ros2/Visualizing_ROS_2_data_with_Foxglove_Studio\357\203\201.txt" new file mode 100644 index 0000000..4a3790d --- /dev/null +++ "b/exported_docs/ros2/Visualizing_ROS_2_data_with_Foxglove_Studio\357\203\201.txt" @@ -0,0 +1,18 @@ +Title: Visualizing ROS 2 data with Foxglove Studio +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Visualizing-ROS-2-Data-With-Foxglove-Studio.html +Section: Installation +-------------------------------------------------------------------------------- + +Visualizing ROS 2 data with Foxglove StudioFoxglove Studiois an open source visualization and debugging tool for your robotics data.It is available in a variety of ways to make development as convenient as possible – it can be run as a standalone desktop app, accessed via your browser, or even self-hosted on your own domain.View the source code onGitHub.InstallationTo use the web app, simply open Google Chrome and navigate tostudio.foxglove.dev.To use the desktop app for Linux, macOS, or Windows, download it directly from theFoxglove Studio website.Connect to a data sourceOn opening Foxglove Studio, you will see a dialog with a list ofall possible data sources.To connect to your ROS 2 stack, click “Open connection”, select the “Rosbridge (ROS 1 & 2)” tab, and configure your “WebSocket URL”.You could also drag-and-drop any local ROS 2.db3files directly into the application to load them for playback.NoteIn order toload custom message definitions in your ROS 2 files, try converting them to theMCAP file format.Check out theFoxglove Studio docsfor more detailed instructions.Building layouts with panelsPanelsare modular visualization interfaces that can be configured and arranged into Studiolayouts. +You can also save your layouts for future use, for your own personal reference or with your larger robotics team.Find the full list of available panels in the sidebar’s “Add panel” tab.We’ve highlighted some particularly useful ones below:1 3D: Display visualization markers in a 3D scenePublish marker messages to add primitive shapes (arrows, spheres, etc.) and more complex visualizations (occupancy grids, point clouds, etc.) to your 3D panel’s scene.Choose the topics you want to display via the topic picker on the left, and configure each topic’s visualization settings in the “Edit topic settings” menu.Reference thedocsfor a full list ofsupported message typesand some usefuluser interactions.2 Diagnostics: Filter and sort diagnostics messagesDisplay the status of seen nodes (i.e. stale, error, warn, or OK) from topics with adiagnostic_msgs/msg/DiagnosticArraydatatype in a running feed, and display the diagnostics data for a givendiagnostic_name/hardware_id.Reference thedocsfor more details.3 Image: View camera feed imagesSelect asensor_msgs/msg/Imageorsensor_msgs/msg/CompressedImagetopic to display.Reference thedocsfor more details.4 Log: View log messagesTo viewrcl_interfaces/msg/Logmessages live, use the desktop app toconnectto your running ROS stack. +To viewrcl_interfaces/msg/Logmessages from a pre-recorded data file, you can drag-and-drop your file into either thewebor desktop app.Next, add aLogpanel to your layout. +If you’ve connected to your ROS stack correctly, you should now see a list of your log messages, with the ability to filter them by node name or severity level.Reference thedocsfor more details.5 Plot: Plot arbitrary values over timePlot arbitrary values from your topics’ message paths over playback time.Specify the topic values you want to plot along the y-axis. +For the x-axis, choose between plotting the y-axis value’s timestamp, element index, or another custom topic message path.Reference thedocsfor more details.6 Raw Messages: View incoming topic messagesDisplay incoming topic data in an easy-to-read collapsible JSON tree format.Reference thedocsfor more details.7 Teleop: Teleoperate your robotTeleoperate your physical robot by publishinggeometry_msgs/msg/Twistmessages on a given topic back to your live ROS stack.Reference thedocsfor more details.8 URDF Viewer: View and manipulate your URDF modelTo visualize and control your robot model in Foxglove Studio, open the web or desktop application and add aURDF Viewerpanel to your layout. +Then, drag and drop your URDF file into that panel to visualize your robot model.Select any topic publishing aJointStatemessage to update the visualization based on the published joint states (defaults to/joint_states).Toggle to “Manual joint control” to set joint positions using the provided controls.Reference thedocsfor more details.Other basic actions1 View your ROS graphUsing the desktop app,connectto your running ROS stack. +Next, add aTopic Graphpanel to your layout. +If you’ve connected to your ROS stack correctly, you should now see a computational graph of your ROS nodes, topics, and services in that panel. +Use the controls on the right side of the panel to select which topics to display or to toggle services.2 View and edit your ROS paramsUsing the desktop app,connectto your running ROS stack. +Next, add aParameterspanel to your layout. +If you’ve connected to your ROS stack correctly, you should now see a live view of your currentrosparams. +You can edit these parameter values to publishrosparamupdates back to your ROS stack.3 Publish messages back to your live ROS stackUsing the desktop app,connectto your running ROS stack. +Next, add aPublishpanel to your layout.Specify the topic you want to publish on to infer its datatype and populate the text field with a JSON message template.Selecting a datatype in the dropdown of common ROS datatypes will also populate the text field with a JSON message template.Edit the template to customize your message before hitting “Publish”. \ No newline at end of file diff --git "a/exported_docs/ros2/Webots\357\203\201.txt" "b/exported_docs/ros2/Webots\357\203\201.txt" new file mode 100644 index 0000000..c1a8cd5 --- /dev/null +++ "b/exported_docs/ros2/Webots\357\203\201.txt" @@ -0,0 +1,6 @@ +Title: Webots +URL: https://docs.ros.org/en/jazzy/Tutorials/Advanced/Simulators/Webots/Simulation-Webots.html +Section: Installation +-------------------------------------------------------------------------------- + +WebotsThis set of tutorials will teach you how to configure the Webots simulator with ROS 2.Installation (Ubuntu)Installation (Windows)Installation (macOS)Setting up a robot simulation (Basic)Setting up a robot simulation (Advanced)Setting up a Reset HandlerThe Ros2Supervisor Node \ No newline at end of file diff --git "a/exported_docs/ros2/Windows_(binary)\357\203\201.txt" "b/exported_docs/ros2/Windows_(binary)\357\203\201.txt" new file mode 100644 index 0000000..3e5f532 --- /dev/null +++ "b/exported_docs/ros2/Windows_(binary)\357\203\201.txt" @@ -0,0 +1,69 @@ +Title: Windows (binary) +URL: https://docs.ros.org/en/jazzy/Installation/Windows-Install-Binary.html +Section: Installation +-------------------------------------------------------------------------------- + +Windows (binary)Table of ContentsSystem requirementsSystem setupInstall ChocolateyInstall PythonInstall Visual C++ RedistributablesInstall OpenSSLInstall Visual StudioInstall OpenCVInstall dependenciesInstall miscellaneous prerequisitesInstall Qt5RQt dependenciesInstall ROS 2Install additional RMW implementations (optional)Setup environmentTry some examplesNext stepsTroubleshootUninstallExtra Stuff for DebugThis page explains how to install ROS 2 on Windows from a pre-built binary package.NoteThe pre-built binary does not include all ROS 2 packages. +All packages in theROS base variantare included, and only a subset of packages in theROS desktop variantare included. +The exact list of packages are described by the repositories listed inthis ros2.repos file.System requirementsOnly Windows 10 is supported.System setupInstall ChocolateyChocolatey is a package manager for Windows, install it by following their installation instructions:https://chocolatey.org/installYou’ll use Chocolatey to install some other developer tools.Install PythonOpen a Command Prompt and type the following to install Python via Chocolatey:chocoinstall-ypython--version3.8.3NoteChocolatey will install Python inC:\Python38, and the rest of the installation expects it to be there. +If you’ve installed Python somewhere else, you must copy or link it to that location.Install Visual C++ RedistributablesOpen a Command Prompt and type the following to install them via Chocolatey:chocoinstall-yvcredist2013vcredist140Install OpenSSLOpen a Command Prompt and type the following to install OpenSSL via Chocolatey:chocoinstall-yopenssl--version1.1.1.2100This command sets an environment variable that persists over sessions:setx/mOPENSSL_CONF"C:\Program Files\OpenSSL-Win64\bin\openssl.cfg"You will need to append the OpenSSL-Win64 bin folder to your PATH. +You can do this by clicking the Windows icon, typing “Environment Variables”, then clicking on “Edit the system environment variables”. +In the resulting dialog, click “Environment Variables”, then click “Path” on the bottom pane, finally click “Edit” and add the path below.C:\ProgramFiles\OpenSSL-Win64\bin\Install Visual StudioInstall Visual Studio 2019.If you already have a paid version of Visual Studio 2019 (Professional, Enterprise), skip this step.Microsoft provides a free of charge version of Visual Studio 2019, named Community, which can be used to build applications that use ROS 2.You can download the installer directly through this link.Make sure that the Visual C++ features are installed.An easy way to make sure they’re installed is to select theDesktopdevelopmentwithC++workflow during the install.Make sure that no C++ CMake tools are installed by unselecting them in the list of components to be installed.Install OpenCVSome of the examples require OpenCV to be installed.You can download a precompiled version of OpenCV 3.4.6 fromhttps://github.com/ros2/ros2/releases/download/opencv-archives/opencv-3.4.6-vc16.VS2019.zip.Assuming you unpacked it toC:\opencv, type the following on a Command Prompt (requires Admin privileges):setx/mOpenCV_DIRC:\opencvSince you are using a precompiled ROS version, we have to tell it where to find the OpenCV libraries. +You have to extend thePATHvariable toC:\opencv\x64\vc16\bin.Install dependenciesThere are a few dependencies not available in the Chocolatey package database. +In order to ease the manual installation process, we provide the necessary Chocolatey packages.As some chocolatey packages rely on it, we start by installing CMakechocoinstall-ycmakeYou will need to append the CMake bin folderC:\ProgramFiles\CMake\binto your PATH.Please download these packages fromthisGitHub repository.asio.1.12.1.nupkgbullet.3.17.nupkgcunit.2.1.3.nupkgeigen.3.3.4.nupkgtinyxml2.6.0.0.nupkgOnce these packages are downloaded, open an administrative shell and execute the following command:chocoinstall-y-sasiocuniteigentinyxml2bulletPlease replacewith the folder you downloaded the packages to.First upgrade pip and setuptools:python-mpipinstall-Upipsetuptools==59.6.0Now install some additional python dependencies:python-mpipinstall-Ucatkin_pkgcryptographyempyimportlib-metadatajsonschemalark==1.1.1lxmlmatplotlibnetifacesnumpyopencv-pythonPyQt5pillowpsutilpycairopydotpyparsing==2.4.7pytestpyyamlrosdistroInstall miscellaneous prerequisitesNext install xmllint:Download the64 bit binary archivesoflibxml2(and its dependenciesiconvandzlib) fromhttps://www.zlatkovic.com/projects/libxml/Unpack all archives into e.g.C:\xmllintAddC:\xmllint\binto thePATH.Install Qt5Download the5.12.X offline installerfrom Qt’s website. +Run the installer. +Make sure to select theMSVC201764-bitcomponent under theQt->Qt5.12.12tree.Finally, in an administratorcmd.exewindow set these environment variables. +The commands below assume you installed it to the default location ofC:\Qt.setx/mQt5_DIRC:\Qt\Qt5.12.12\5.12.12\msvc2017_64 +setx/mQT_QPA_PLATFORM_PLUGIN_PATHC:\Qt\Qt5.12.12\5.12.12\msvc2017_64\plugins\platformsNoteThis path might change based on the installed MSVC version, the directory Qt was installed to, and the version of Qt installed.RQt dependenciesTo run rqt_graph you need todownloadand installGraphviz. +The installer will ask if to add graphviz to PATH, choose to either add it to the current user or all users.Install ROS 2Go to the releases page:https://github.com/ros2/ros2/releasesDownload the latest package for Windows, e.g.,ros2-jazzy-*-windows-release-amd64.zip.NoteThere may be more than one binary download option which might cause the file name to differ.NoteTo install debug libraries for ROS 2, seeExtra Stuff for Debug. +Then continue on with downloadingros2-jazzy-*-windows-debug-amd64.zip.Unpack the zip file somewhere (we’ll assumeC:\dev\ros2_jazzy).Install additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at runtime. +See theguideon how to work with multiple RMWs.Setup environmentStart a command shell and source the ROS 2 setup file to set up the workspace:callC:\dev\ros2_jazzy\local_setup.batIt is normal that the previous command, if nothing else went wrong, outputs “The system cannot find the path specified.” exactly once.Try some examplesIn a command shell, set up the ROS 2 environment as described above and then run a C++talker:ros2rundemo_nodes_cpptalkerStart another command shell and run a Pythonlistener:ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you installed your workspace with colcon as instructed above, “uninstalling” could be just a matter of opening a new terminal and not sourcing the workspace’ssetupfile. +This way, your environment will behave as though there is no Jazzy install on your system.If you’re also trying to free up space, you can delete the entire workspace directory with:rmdir/s/q\ros2_jazzyExtra Stuff for DebugTo download the ROS 2 debug libraries you’ll need to downloadros2-jazzy-*-windows-debug-AMD64.zip. +Please note that debug libraries require some more additional configuration/setup to work as given below.Python installation may require modification to enable debugging symbols and debug binaries:Search in windowsSearch Barand openApps and Features.Search for the installed Python version.Click Modify.Click Next to go toAdvanced Options.Make sureDownload debugging symbolsandDownload debug binariesare checked.Click Install. + +Code Examples: + +Language: unknown +chocoinstall-ypython--version3.8.3 + +Language: unknown +chocoinstall-yvcredist2013vcredist140 + +Language: unknown +chocoinstall-yopenssl--version1.1.1.2100 + +Language: unknown +setx/mOPENSSL_CONF"C:\Program Files\OpenSSL-Win64\bin\openssl.cfg" + +Language: unknown +setx/mOpenCV_DIRC:\opencv + +Language: unknown +chocoinstall-ycmake + +Language: unknown +chocoinstall-y-sasiocuniteigentinyxml2bullet + +Language: unknown +python-mpipinstall-Upipsetuptools==59.6.0 + +Language: unknown +python-mpipinstall-Ucatkin_pkgcryptographyempyimportlib-metadatajsonschemalark==1.1.1lxmlmatplotlibnetifacesnumpyopencv-pythonPyQt5pillowpsutilpycairopydotpyparsing==2.4.7pytestpyyamlrosdistro + +Language: unknown +setx/mQt5_DIRC:\Qt\Qt5.12.12\5.12.12\msvc2017_64 +setx/mQT_QPA_PLATFORM_PLUGIN_PATHC:\Qt\Qt5.12.12\5.12.12\msvc2017_64\plugins\platforms + +Language: unknown +callC:\dev\ros2_jazzy\local_setup.bat + +Language: unknown +ros2rundemo_nodes_cpptalker + +Language: unknown +ros2rundemo_nodes_pylistener + +Language: unknown +rmdir/s/q\ros2_jazzy diff --git "a/exported_docs/ros2/Windows_(source)\357\203\201.txt" "b/exported_docs/ros2/Windows_(source)\357\203\201.txt" new file mode 100644 index 0000000..1098081 --- /dev/null +++ "b/exported_docs/ros2/Windows_(source)\357\203\201.txt" @@ -0,0 +1,143 @@ +Title: Windows (source) +URL: https://docs.ros.org/en/jazzy/Installation/Alternatives/Windows-Development-Setup.html +Section: Installation +-------------------------------------------------------------------------------- + +Windows (source)Table of ContentsSystem requirementsLanguage supportSystem setupInstall ChocolateyInstall PythonInstall Visual C++ RedistributablesInstall OpenSSLInstall Visual StudioInstall OpenCVInstall dependenciesInstall miscellaneous prerequisitesInstall Qt5RQt dependenciesInstall additional prerequisites from ChocolateyInstall Python prerequisitesBuild ROS 2Get ROS 2 codeInstall additional RMW implementations (optional)Build the code in the workspaceSetup environmentTry some examplesNext stepsExtra stuff for Debug modeStay up to dateTroubleshootUninstallThis guide is about how to setup a development environment for ROS 2 on Windows.System requirementsOnly Windows 10 is supported.Language supportMake sure you have a locale which supportsUTF-8. +For example, for a Chinese-language Windows 10 installation, you may need to install anEnglish language pack.System setupInstall ChocolateyChocolatey is a package manager for Windows, install it by following their installation instructions:https://chocolatey.org/installYou’ll use Chocolatey to install some other developer tools.Install PythonOpen a Command Prompt and type the following to install Python via Chocolatey:chocoinstall-ypython--version3.8.3NoteChocolatey will install Python inC:\Python38, and the rest of the installation expects it to be there. +If you’ve installed Python somewhere else, you must copy or link it to that location.Install Visual C++ RedistributablesOpen a Command Prompt and type the following to install them via Chocolatey:chocoinstall-yvcredist2013vcredist140Install OpenSSLOpen a Command Prompt and type the following to install OpenSSL via Chocolatey:chocoinstall-yopenssl--version1.1.1.2100This command sets an environment variable that persists over sessions:setx/mOPENSSL_CONF"C:\Program Files\OpenSSL-Win64\bin\openssl.cfg"You will need to append the OpenSSL-Win64 bin folder to your PATH. +You can do this by clicking the Windows icon, typing “Environment Variables”, then clicking on “Edit the system environment variables”. +In the resulting dialog, click “Environment Variables”, then click “Path” on the bottom pane, finally click “Edit” and add the path below.C:\ProgramFiles\OpenSSL-Win64\bin\Install Visual StudioInstall Visual Studio 2019.If you already have a paid version of Visual Studio 2019 (Professional, Enterprise), skip this step.Microsoft provides a free of charge version of Visual Studio 2019, named Community, which can be used to build applications that use ROS 2.You can download the installer directly through this link.Make sure that the Visual C++ features are installed.An easy way to make sure they’re installed is to select theDesktopdevelopmentwithC++workflow during the install.Make sure that no C++ CMake tools are installed by unselecting them in the list of components to be installed.Install OpenCVSome of the examples require OpenCV to be installed.You can download a precompiled version of OpenCV 3.4.6 fromhttps://github.com/ros2/ros2/releases/download/opencv-archives/opencv-3.4.6-vc16.VS2019.zip.Assuming you unpacked it toC:\opencv, type the following on a Command Prompt (requires Admin privileges):setx/mOpenCV_DIRC:\opencvSince you are using a precompiled ROS version, we have to tell it where to find the OpenCV libraries. +You have to extend thePATHvariable toC:\opencv\x64\vc16\bin.Install dependenciesThere are a few dependencies not available in the Chocolatey package database. +In order to ease the manual installation process, we provide the necessary Chocolatey packages.As some chocolatey packages rely on it, we start by installing CMakechocoinstall-ycmakeYou will need to append the CMake bin folderC:\ProgramFiles\CMake\binto your PATH.Please download these packages fromthisGitHub repository.asio.1.12.1.nupkgbullet.3.17.nupkgcunit.2.1.3.nupkgeigen.3.3.4.nupkgtinyxml2.6.0.0.nupkgOnce these packages are downloaded, open an administrative shell and execute the following command:chocoinstall-y-sasiocuniteigentinyxml2bulletPlease replacewith the folder you downloaded the packages to.First upgrade pip and setuptools:python-mpipinstall-Upipsetuptools==59.6.0Now install some additional python dependencies:python-mpipinstall-Ucatkin_pkgcryptographyempyimportlib-metadatajsonschemalark==1.1.1lxmlmatplotlibnetifacesnumpyopencv-pythonPyQt5pillowpsutilpycairopydotpyparsing==2.4.7pytestpyyamlrosdistroInstall miscellaneous prerequisitesNext install xmllint:Download the64 bit binary archivesoflibxml2(and its dependenciesiconvandzlib) fromhttps://www.zlatkovic.com/projects/libxml/Unpack all archives into e.g.C:\xmllintAddC:\xmllint\binto thePATH.Install Qt5Download the5.12.X offline installerfrom Qt’s website. +Run the installer. +Make sure to select theMSVC201764-bitcomponent under theQt->Qt5.12.12tree.Finally, in an administratorcmd.exewindow set these environment variables. +The commands below assume you installed it to the default location ofC:\Qt.setx/mQt5_DIRC:\Qt\Qt5.12.12\5.12.12\msvc2017_64 +setx/mQT_QPA_PLATFORM_PLUGIN_PATHC:\Qt\Qt5.12.12\5.12.12\msvc2017_64\plugins\platformsNoteThis path might change based on the installed MSVC version, the directory Qt was installed to, and the version of Qt installed.RQt dependenciesTo run rqt_graph you need todownloadand installGraphviz. +The installer will ask if to add graphviz to PATH, choose to either add it to the current user or all users.Install additional prerequisites from Chocolateychocoinstall-ycppcheckcurlgitwinflexbison3You will need to append the Git cmd folderC:\ProgramFiles\Git\cmdto the PATH (you can do this by clicking the Windows icon, typing “Environment Variables”, then clicking on “Edit the system environment variables”. +In the resulting dialog, click “Environment Variables”, the click “Path” on the bottom pane, then click “Edit” and add the path).Install Python prerequisitesInstall additional Python dependencies:pipinstall-Ucolcon-common-extensionscoverageflake8flake8-blind-exceptflake8-builtinsflake8-class-newlineflake8-comprehensionsflake8-deprecatedflake8-docstringsflake8-import-orderflake8-quotesmockmypy==0.931pep8pydocstylepytestpytest-covpytest-mockpytest-repeatpytest-rerunfailurespytest-runnervcstoolBuild ROS 2Get ROS 2 codeNow that we have the development tools we can get the ROS 2 source code.First setup a development folder, for exampleC:\jazzy:NoteIt is very important that the chosen path is short, due to the short default Windows path limits (260 characters). +To allow longer paths, seehttps://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry.md\jazzy\srccd\jazzyGet theros2.reposfile which defines the repositories to clone from:vcsimport--inputhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repossrcInstall additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at build or runtime. +See theguideon how to work with multiple RMWs.Build the code in the workspaceTo build ROS 2 you will need a Visual Studio Command Prompt (“x64 Native Tools Command Prompt for VS 2019”) running as Administrator.To build the\jazzyfolder tree:colconbuild--merge-installNoteWe’re using--merge-installhere to avoid aPATHvariable that is too long at the end of the build. +If you’re adapting these instructions to build a smaller workspace then you might be able to use the default behavior which is isolated install, i.e. where each package is installed to a different folder.NoteIf you are doing a debug build usepython_dpath\to\colcon_executablecolcon. +SeeExtra stuff for debug modefor more info on running Python code in debug builds on Windows.Setup environmentStart a command shell and source the ROS 2 setup file to set up the workspace:callC:\jazzy\install\local_setup.batThis will automatically set up the environment for any DDS vendors that support was built for.It is normal that the previous command, if nothing else went wrong, outputs “The system cannot find the path specified.” exactly once.Try some examplesNote that the first time you run any executable you will have to allow access to the network through a Windows Firewall popup.You can run the tests using this command:colcontest--merge-installNote--merge-installshould only be used if it was also used in the build step.Afterwards you can get a summary of the tests using this command:colcontest-resultTo run the examples, first open a clean newcmd.exeand set up the workspace by sourcing thelocal_setup.batfile. +Then, run a C++talker:callinstall\local_setup.bat +ros2rundemo_nodes_cpptalkerIn a separate shell you can do the same, but instead run a Pythonlistener:callinstall\local_setup.bat +ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!NoteIt is not recommended to build in the same cmd prompt that you’ve sourced thelocal_setup.bat.Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.Extra stuff for Debug modeIf you want to be able to run all the tests in Debug mode, you’ll need to install a few more things:To be able to extract the Python source tarball, you can use PeaZip:chocoinstall-ypeazipYou’ll also need SVN, since some of the Python source-build dependencies are checked out via SVN:chocoinstall-ysvnhgYou’ll need to quit and restart the command prompt after installing the above.Get and extract the Python 3.8.3 source from thetgz:https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgzTo keep these instructions concise, please extract it toC:\dev\Python-3.8.3Now, build the Python source in debug mode from a Visual Studio command prompt:cdC:\dev\Python-3.8.3\PCbuild +get_externals.bat +build.bat-px64-dFinally, copy the build products into the Python38 installation directories, next to the Release-mode Python executable and DLL’s:cdC:\dev\Python-3.8.3\PCbuild\amd64 +copypython_d.exeC:\Python38/Y +copypython38_d.dllC:\Python38/Y +copypython3_d.dllC:\Python38/Y +copypython38_d.libC:\Python38\libs/Y +copypython3_d.libC:\Python38\libs/Y +copysqlite3_d.dllC:\Python38\DLLs/Yfor%Iin(*_d.pyd)docopy%IC:\Python38\DLLs/YNow, from a fresh command prompt, make sure thatpython_dworks:python_d-c"import _ctypes ; import coverage"Once you have verified the operation ofpython_d, it is necessary to reinstall a few dependencies with the debug-enabled libraries:python_d-mpipinstall--force-reinstallhttps://github.com/ros2/ros2/releases/download/numpy-archives/numpy-1.18.4-cp38-cp38d-win_amd64.whl +python_d-mpipinstall--force-reinstallhttps://github.com/ros2/ros2/releases/download/lxml-archives/lxml-4.5.1-cp38-cp38d-win_amd64.whlTo verify the installation of these dependencies:python_d-c"from lxml import etree ; import numpy"When you wish to return to building release binaries, it is necessary to uninstall the debug variants and use the release variants:python-mpipuninstallnumpylxml +python-mpipinstallnumpylxmlTo create executables python scripts(.exe), python_d should be used to invoke colconpython_dpath\to\colcon_executablebuildHooray, you’re done!Stay up to dateSeeMaintain source checkoutto periodically refresh your source installation.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you installed your workspace with colcon as instructed above, “uninstalling” could be just a matter of opening a new terminal and not sourcing the workspace’ssetupfile. +This way, your environment will behave as though there is no Jazzy install on your system.If you’re also trying to free up space, you can delete the entire workspace directory with:rmdir/s/q\ros2_jazzy + +Code Examples: + +Language: unknown +chocoinstall-ypython--version3.8.3 + +Language: unknown +chocoinstall-yvcredist2013vcredist140 + +Language: unknown +chocoinstall-yopenssl--version1.1.1.2100 + +Language: unknown +setx/mOPENSSL_CONF"C:\Program Files\OpenSSL-Win64\bin\openssl.cfg" + +Language: unknown +setx/mOpenCV_DIRC:\opencv + +Language: unknown +chocoinstall-ycmake + +Language: unknown +chocoinstall-y-sasiocuniteigentinyxml2bullet + +Language: unknown +python-mpipinstall-Upipsetuptools==59.6.0 + +Language: unknown +python-mpipinstall-Ucatkin_pkgcryptographyempyimportlib-metadatajsonschemalark==1.1.1lxmlmatplotlibnetifacesnumpyopencv-pythonPyQt5pillowpsutilpycairopydotpyparsing==2.4.7pytestpyyamlrosdistro + +Language: unknown +setx/mQt5_DIRC:\Qt\Qt5.12.12\5.12.12\msvc2017_64 +setx/mQT_QPA_PLATFORM_PLUGIN_PATHC:\Qt\Qt5.12.12\5.12.12\msvc2017_64\plugins\platforms + +Language: unknown +chocoinstall-ycppcheckcurlgitwinflexbison3 + +Language: unknown +pipinstall-Ucolcon-common-extensionscoverageflake8flake8-blind-exceptflake8-builtinsflake8-class-newlineflake8-comprehensionsflake8-deprecatedflake8-docstringsflake8-import-orderflake8-quotesmockmypy==0.931pep8pydocstylepytestpytest-covpytest-mockpytest-repeatpytest-rerunfailurespytest-runnervcstool + +Language: unknown +md\jazzy\srccd\jazzy + +Language: unknown +vcsimport--inputhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repossrc + +Language: unknown +colconbuild--merge-install + +Language: unknown +callC:\jazzy\install\local_setup.bat + +Language: unknown +colcontest--merge-install + +Language: unknown +colcontest-result + +Language: unknown +callinstall\local_setup.bat +ros2rundemo_nodes_cpptalker + +Language: unknown +callinstall\local_setup.bat +ros2rundemo_nodes_pylistener + +Language: unknown +chocoinstall-ypeazip + +Language: unknown +chocoinstall-ysvnhg + +Language: unknown +cdC:\dev\Python-3.8.3\PCbuild +get_externals.bat +build.bat-px64-d + +Language: unknown +cdC:\dev\Python-3.8.3\PCbuild\amd64 +copypython_d.exeC:\Python38/Y +copypython38_d.dllC:\Python38/Y +copypython3_d.dllC:\Python38/Y +copypython38_d.libC:\Python38\libs/Y +copypython3_d.libC:\Python38\libs/Y +copysqlite3_d.dllC:\Python38\DLLs/Yfor%Iin(*_d.pyd)docopy%IC:\Python38\DLLs/Y + +Language: unknown +python_d-c"import _ctypes ; import coverage" + +Language: unknown +python_d-mpipinstall--force-reinstallhttps://github.com/ros2/ros2/releases/download/numpy-archives/numpy-1.18.4-cp38-cp38d-win_amd64.whl +python_d-mpipinstall--force-reinstallhttps://github.com/ros2/ros2/releases/download/lxml-archives/lxml-4.5.1-cp38-cp38d-win_amd64.whl + +Language: unknown +python_d-c"from lxml import etree ; import numpy" + +Language: unknown +python-mpipuninstallnumpylxml +python-mpipinstallnumpylxml + +Language: unknown +python_dpath\to\colcon_executablebuild + +Language: unknown +rmdir/s/q\ros2_jazzy diff --git "a/exported_docs/ros2/Working_with_multiple_ROS_2_middleware_implementations\357\203\201.txt" "b/exported_docs/ros2/Working_with_multiple_ROS_2_middleware_implementations\357\203\201.txt" new file mode 100644 index 0000000..8ccf9ca --- /dev/null +++ "b/exported_docs/ros2/Working_with_multiple_ROS_2_middleware_implementations\357\203\201.txt" @@ -0,0 +1,57 @@ +Title: Working with multiple ROS 2 middleware implementations +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Working-with-multiple-RMW-implementations.html +Section: Installation +-------------------------------------------------------------------------------- + +Working with multiple ROS 2 middleware implementationsTable of ContentsPrerequisitesSpecifying RMW implementationsAdding RMW implementations to your workspaceTroubleshootingChecking the Current RMWEnsuring use of a particular RMW implementationRTI Connext on OSX: Failure due to insufficient shared memory kernel settingsThis page explains the default RMW implementation and how to specify an alternative.PrerequisitesYou should have already read theDDS and ROS middleware implementations page.Specifying RMW implementationsTo have multiple RMW implementations available for use you must have installed the ROS 2 binaries and any additional dependencies for specific RMW implementations, or built ROS 2 from source with multiple RMW implementations in the workspace (the RMW implementations are included in the build by default if their compile-time dependencies are met). SeeInstall DDS implementations.Both C++ and Python nodes support an environment variableRMW_IMPLEMENTATIONthat allows the user to select the RMW implementation to use when running ROS 2 applications.The user may set this variable to a specific implementation identifier, such asrmw_cyclonedds_cpp,rmw_fastrtps_cpp,rmw_connextdds, orrmw_gurumdds_cpp.For example, to run the talker demo using the C++ talker and Python listener with the Connext RMW implementation:LinuxmacOSWindowsRMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_cpptalker# Run in another terminalRMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_pylistenerRMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_cpptalker# Run in another terminalRMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_pylistenersetRMW_IMPLEMENTATION=rmw_connextdds +ros2 run demo_nodes_cpp talkerREM run in another terminalsetRMW_IMPLEMENTATION=rmw_connextdds +ros2 run demo_nodes_py listenerAdding RMW implementations to your workspaceSuppose that you have built your ROS 2 workspace with only Fast DDS installed and therefore only the Fast DDS RMW implementation built. +The last time your workspace was built, any other RMW implementation packages,rmw_connextddsfor example, were probably unable to find installations of the relevant DDS implementations. +If you then install an additional DDS implementation, Connext for example, you will need to re-trigger the check for a Connext installation that occurs when the Connext RMW implementation is being built. +You can do this by specifying the--cmake-clean-cacheflag on your next workspace build, and you should see that the RMW implementation package then gets built for the newly installed DDS implementation.It is possible to run into a problem when “rebuilding” the workspace with an additional RMW implementation using the--cmake-clean-cacheoption where the build complains about the default RMW implementation changing. +To resolve this, you can either set the default implementation to what is was before with theRMW_IMPLEMENTATIONCMake argument or you can delete the build folder for packages that complain and continue the build with--packages-start.TroubleshootingChecking the Current RMWTo check the RMW that is currently in use you simply check theRMW_IMPLEMENTATIONenvironment variable. On Linux systemsprintenvprints the full list of environment variables. +Other operating systems will have other procedures for viewing environment variables. +IfRMW_IMPLEMENTATIONis not in the environment it is safe to assume you are using the default for your ROS distro, otherwise the current RMW is the value listed. +The default RMW for each ROS Distro can be found inREP-2000.Ensuring use of a particular RMW implementationIf theRMW_IMPLEMENTATIONenvironment variable is set to an RMW implementation for which support is not installed, you will see an error message similar to the following if you have only one implementation installed:ExpectedRMWimplementationidentifierof'rmw_connextdds'butinsteadfound'rmw_fastrtps_cpp',exitingwith102.If you have support for multiple RMW implementations installed and you request use of one that is not installed, you will see something similar to:ErrorgettingRMWimplementationidentifier/RMWimplementationnotinstalled(expectedidentifierof'rmw_connextdds'),exitingwith1.If this occurs, double check that your ROS 2 installation includes support for the RMW implementation that you have specified in theRMW_IMPLEMENTATIONenvironment variable.If you want to switch between RMW implementations, verify that the ROS 2 daemon process is not running with the previous RMW implementation to avoid any issues between nodes and command line tools such asros2node. +For example, if you run:RMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_cpptalkerandros2nodelistit will generate a daemon with a Fast DDS implementation:2131822.00.653589655044pts/8Sl16:140:00/usr/bin/python3/opt/ros/jazzy/bin/_ros2_daemon--rmw-implementationrmw_fastrtps_cpp--ros-domain-id0Even if you run the command line tool again with the correct RMW implementation, the daemon’s RMW implementation will not change and the ROS 2 command line tools will fail.To solve this, simply stop the daemon process:ros2daemonstopand rerun the ROS 2 command line tool with the correct RMW implementation.RTI Connext on OSX: Failure due to insufficient shared memory kernel settingsIf you receive an error message similar to below when running RTI Connext on OSX:[D0062|ENABLE]DDS_DomainParticipantPresentation_reserve_participant_index_entryports:!enable reserve participant index[D0062|ENABLE]DDS_DomainParticipant_reserve_participant_index_entryports:Unusable shared memory transport. For a more in- depth explanation of the possible problem and solution, please visit https://community.rti.com/kb/osx510.This error is caused by an insufficient number or size of shared memory segments allowed by the operating system. As a result, theDomainParticipantis unable to allocate enough resources and calculate its participant index which causes the error.You can increase the shared memory resources of your machine either temporarily or permanently.To increase the settings temporarily, you can run the following commands as user root:/usr/sbin/sysctl -w kern.sysv.shmmax=419430400/usr/sbin/sysctl -w kern.sysv.shmmin=1/usr/sbin/sysctl -w kern.sysv.shmmni=128/usr/sbin/sysctl -w kern.sysv.shmseg=1024/usr/sbin/sysctl -w kern.sysv.shmall=262144To increase the settings permanently, you will need to edit or create the file/etc/sysctl.conf. Creating or editing this file will require root permissions. Either add to your existingetc/sysctl.conffile or create/etc/sysctl.confwith the following lines:kern.sysv.shmmax=419430400kern.sysv.shmmin=1kern.sysv.shmmni=128kern.sysv.shmseg=1024kern.sysv.shmall=262144You will need to reboot the machine after modifying this file to have the changes take effect.This solution is edited from the RTI Connext community forum. +See theoriginal postfor more detailed explanation. + +Code Examples: + +Language: unknown +RMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_cpptalker# Run in another terminalRMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_pylistener + +Language: unknown +RMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_cpptalker# Run in another terminalRMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_pylistener + +Language: unknown +setRMW_IMPLEMENTATION=rmw_connextdds +ros2 run demo_nodes_cpp talkerREM run in another terminalsetRMW_IMPLEMENTATION=rmw_connextdds +ros2 run demo_nodes_py listener + +Language: unknown +ExpectedRMWimplementationidentifierof'rmw_connextdds'butinsteadfound'rmw_fastrtps_cpp',exitingwith102. + +Language: unknown +ErrorgettingRMWimplementationidentifier/RMWimplementationnotinstalled(expectedidentifierof'rmw_connextdds'),exitingwith1. + +Language: unknown +RMW_IMPLEMENTATION=rmw_connextddsros2rundemo_nodes_cpptalker + +Language: unknown +ros2nodelist + +Language: unknown +2131822.00.653589655044pts/8Sl16:140:00/usr/bin/python3/opt/ros/jazzy/bin/_ros2_daemon--rmw-implementationrmw_fastrtps_cpp--ros-domain-id0 + +Language: unknown +ros2daemonstop + +Language: unknown +[D0062|ENABLE]DDS_DomainParticipantPresentation_reserve_participant_index_entryports:!enable reserve participant index[D0062|ENABLE]DDS_DomainParticipant_reserve_participant_index_entryports:Unusable shared memory transport. For a more in- depth explanation of the possible problem and solution, please visit https://community.rti.com/kb/osx510. + +Language: unknown +/usr/sbin/sysctl -w kern.sysv.shmmax=419430400/usr/sbin/sysctl -w kern.sysv.shmmin=1/usr/sbin/sysctl -w kern.sysv.shmmni=128/usr/sbin/sysctl -w kern.sysv.shmseg=1024/usr/sbin/sysctl -w kern.sysv.shmall=262144 + +Language: unknown +kern.sysv.shmmax=419430400kern.sysv.shmmin=1kern.sysv.shmmni=128kern.sysv.shmseg=1024kern.sysv.shmall=262144 diff --git "a/exported_docs/ros2/Writing_Basic_Tests_with_Python\357\203\201.txt" "b/exported_docs/ros2/Writing_Basic_Tests_with_Python\357\203\201.txt" new file mode 100644 index 0000000..b109117 --- /dev/null +++ "b/exported_docs/ros2/Writing_Basic_Tests_with_Python\357\203\201.txt" @@ -0,0 +1,25 @@ +Title: Writing Basic Tests with Python +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Testing/Python.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing Basic Tests with PythonStarting point: we’ll assume you have abasic ament_python packageset up already and you want to add some tests to it.If you are using ament_cmake_python, refer to the theament_cmake_python docsfor how to make tests dicoverable. +The test contents and invocation withcolconremain the same.Package Setupsetup.pyYoursetup.pymust have a test dependency onpytestwithin the call tosetup(...):tests_require=['pytest'],Test Files and FoldersYour test code needs to go in a folder namedtestsin the root of your package.Any file that contains tests that you want to run must have the patterntest_FOO.pywhereFOOcan be replaced with anything.Example package layout:awesome_ros_package/awesome_ros_package/__init__.pyfozzie.pypackage.xmlsetup.cfgsetup.pytests/test_init.pytest_copyright.pytest_fozzie.pyTest ContentsYou can now write tests to your heart’s content. There areplenty of resources on pytest, but in short, you can write functions with thetest_prefix and include whatever assert statements you’d like.deftest_math():assert2+2==5# This should fail for most mathematical systemsRunning TestsSee thetutorial on how to run tests from the command linefor more information on running the tests and inspecting the test results.Special CommandsBeyond thestandard colcon testing commandsyou can also specify arguments to thepytestframework from the command line with the--pytest-argsflag. +For example, you can specify the name of the function to run withcolcon test --packages-select --pytest-args -k name_of_the_test_functionTo see the pytest output while running the tests, use these flags:colcon test --event-handlers console_cohesion+ + +Code Examples: + +Language: unknown +tests_require=['pytest'], + +Language: unknown +awesome_ros_package/awesome_ros_package/__init__.pyfozzie.pypackage.xmlsetup.cfgsetup.pytests/test_init.pytest_copyright.pytest_fozzie.py + +Language: unknown +deftest_math():assert2+2==5# This should fail for most mathematical systems + +Language: unknown +colcon test --packages-select --pytest-args -k name_of_the_test_function + +Language: unknown +colcon test --event-handlers console_cohesion+ diff --git "a/exported_docs/ros2/Writing_a_broadcaster_(C++)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_broadcaster_(C++)\357\203\201.txt" new file mode 100644 index 0000000..fed3172 --- /dev/null +++ "b/exported_docs/ros2/Writing_a_broadcaster_(C++)\357\203\201.txt" @@ -0,0 +1,105 @@ +Title: Writing a broadcaster (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Cpp.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a broadcaster (C++)Goal:Learn how to broadcast the state of a robot to tf2.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Write the broadcaster node2 Write the launch file3 Build4 RunSummaryBackgroundIn the next two tutorials we will write the code to reproduce the demo from theIntroduction to tf2tutorial. +After that, the following tutorials focus on extending the demo with more advanced tf2 features, including the usage of timeouts in transformation lookups and time travel.PrerequisitesThis tutorial assumes you have a working knowledge of ROS 2 and you have completed theIntroduction to tf2 tutorialandtf2 static broadcaster tutorial (C++). +We’ll be reusing thelearning_tf2_cpppackage from that last tutorial.In previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Write the broadcaster nodeLet’s first create the source files. +Go to thelearning_tf2_cpppackage we created in the previous tutorial. +Inside thesrcdirectory download the example broadcaster code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cppwget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cppIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cpp -o turtle_tf2_broadcaster.cppOr in powershell:curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cpp -o turtle_tf2_broadcaster.cppOpen the file using your preferred text editor.#include#include#include#include#include"geometry_msgs/msg/transform_stamped.hpp"#include"rclcpp/rclcpp.hpp"#include"tf2/LinearMath/Quaternion.h"#include"tf2_ros/transform_broadcaster.h"#include"turtlesim/msg/pose.hpp"classFramePublisher:publicrclcpp::Node{public:FramePublisher():Node("turtle_tf2_frame_publisher"){// Declare and acquire `turtlename` parameterturtlename_=this->declare_parameter("turtlename","turtle");// Initialize the transform broadcastertf_broadcaster_=std::make_unique(*this);// Subscribe to a turtle{1}{2}/pose topic and call handle_turtle_pose// callback function on each messagestd::ostringstreamstream;stream<<"/"<msg){geometry_msgs::msg::TransformStampedt;// Read message content and assign it to// corresponding tf variablest.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=turtlename_.c_str();// Turtle only exists in 2D, thus we get x and y translation// coordinates from the message and set the z coordinate to 0t.transform.translation.x=msg->x;t.transform.translation.y=msg->y;t.transform.translation.z=0.0;// For the same reason, turtle can only rotate around one axis// and this why we set rotation in x and y to 0 and obtain// rotation in z axis from the messagetf2::Quaternionq;q.setRPY(0,0,msg->theta);t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w();// Send the transformationtf_broadcaster_->sendTransform(t);};subscription_=this->create_subscription(topic_name,10,handle_turtle_pose);}private:rclcpp::Subscription::SharedPtrsubscription_;std::unique_ptrtf_broadcaster_;std::stringturtlename_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}1.1 Examine the codeNow, let’s take a look at the code that is relevant to publishing the turtle pose to tf2. +Firstly, we define and acquire a single parameterturtlename, which specifies a turtle name, e.g.turtle1orturtle2.turtlename_=this->declare_parameter("turtlename","turtle");Afterward, the node subscribes to topicturtleX/poseand runs functionhandle_turtle_poseon every incoming message.subscription_=this->create_subscription(topic_name,10,handle_turtle_pose);Now, we create aTransformStampedobject and give it the appropriate metadata.We need to give the transform being published a timestamp, and we’ll just stamp it with the current time by callingthis->get_clock()->now(). This will return the current time used by theNode.Then we need to set the name of the parent frame of the link we’re creating, in this caseworld.Finally, we need to set the name of the child node of the link we’re creating, in this case this is the name of the turtle itself.The handler function for the turtle pose message broadcasts this turtle’s translation and rotation, and publishes it as a transform from frameworldto frameturtleX.geometry_msgs::msg::TransformStampedt;// Read message content and assign it to// corresponding tf variablest.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=turtlename_.c_str();Here we copy the information from the 3D turtle pose into the 3D transform.// Turtle only exists in 2D, thus we get x and y translation// coordinates from the message and set the z coordinate to 0t.transform.translation.x=msg->x;t.transform.translation.y=msg->y;t.transform.translation.z=0.0;// For the same reason, turtle can only rotate around one axis// and this why we set rotation in x and y to 0 and obtain// rotation in z axis from the messagetf2::Quaternionq;q.setRPY(0,0,msg->theta);t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w();Finally we take the transform that we constructed and pass it to thesendTransformmethod of theTransformBroadcasterthat will take care of broadcasting.// Send the transformationtf_broadcaster_->sendTransform(t);1.2 CMakeLists.txtNavigate one level back to thelearning_tf2_cppdirectory, where theCMakeLists.txtandpackage.xmlfiles are located.Now open theCMakeLists.txtadd the executable and name itturtle_tf2_broadcaster, which you’ll use later withros2run.add_executable(turtle_tf2_broadcaster src/turtle_tf2_broadcaster.cpp)ament_target_dependencies(turtle_tf2_broadcastergeometry_msgsrclcpptf2tf2_rosturtlesim)Finally, add theinstall(TARGETS…)section soros2runcan find your executable:install(TARGETSturtle_tf2_broadcasterDESTINATION lib/${PROJECT_NAME})2 Write the launch fileNow create a launch file for this demo. +Create alaunchfolder in thesrc/learning_tf2_cppdirectory. +With your text editor, create a new file calledturtle_tf2_demo_launch.pyin thelaunchfolder, and add the following lines:fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_cpp',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),])2.1 Examine the codeFirst we import required modules from thelaunchandlaunch_rospackages. +It should be noted thatlaunchis a generic launching framework (not ROS 2 specific) andlaunch_roshas ROS 2 specific things, like nodes that we import here.fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodeNow we run our nodes that start the turtlesim simulation and broadcastturtle1state to the tf2 using ourturtle_tf2_broadcasternode.Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_cpp',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),2.2 Add dependenciesNavigate one level back to thelearning_tf2_cppdirectory, where theCMakeLists.txtandpackage.xmlfiles are located.Openpackage.xmlwith your text editor. +Add the following dependencies corresponding to your launch file’s import statements:launchlaunch_rosThis declares the additional requiredlaunchandlaunch_rosdependencies when its code is executed.Make sure to save the file.2.3 CMakeLists.txtReopenCMakeLists.txtand add the line so that the launch files from thelaunch/folder will be installed.install(DIRECTORY launchDESTINATION share/${PROJECT_NAME})You can learn more about creating launch files inthis tutorial.3 BuildRunrosdepin the root of your workspace to check for missing dependencies.LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfStill in the root of your workspace, build your package:LinuxmacOSWindowscolcon build --packages-select learning_tf2_cppcolcon build --packages-select learning_tf2_cppcolcon build --merge-install --packages-select learning_tf2_cppOpen a new terminal, navigate to the root of your workspace, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bash#CMDcall install\setup.bat#Powershell.\install\setup.ps14 RunNow run the launch file that will start the turtlesim simulation node andturtle_tf2_broadcasternode:ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.pyIn the second terminal window type the following command:ros2 run turtlesim turtle_teleop_keyYou will now see that the turtlesim simulation have started with one turtle that you can control.Now, use thetf2_echotool to check if the turtle pose is actually getting broadcast to tf2:ros2 run tf2_ros tf2_echo world turtle1This should show you the pose of the first turtle. +Drive around the turtle using the arrow keys (make sure yourturtle_teleop_keyterminal window is active, not your simulator window). +In your console output you will see something similar to this:At time 1625137663.912474878- Translation: [5.276, 7.930, 0.000]- Rotation: in Quaternion [0.000, 0.000, 0.934, -0.357]At time 1625137664.950813527- Translation: [3.750, 6.563, 0.000]- Rotation: in Quaternion [0.000, 0.000, 0.934, -0.357]At time 1625137665.906280726- Translation: [2.320, 5.282, 0.000]- Rotation: in Quaternion [0.000, 0.000, 0.934, -0.357]At time 1625137666.850775673- Translation: [2.153, 5.133, 0.000]- Rotation: in Quaternion [0.000, 0.000, -0.365, 0.931]If you runtf2_echofor the transform between theworldandturtle2, you should not see a transform, because the second turtle is not there yet. +However, as soon as we add the second turtle in the next tutorial, the pose ofturtle2will be broadcast to tf2.SummaryIn this tutorial you learned how to broadcast the pose of the robot (position and orientation of the turtle) to tf2 and how to use thetf2_echotool. +To actually use the transforms broadcasted to tf2, you should move on to the next tutorial about creating atf2 listener. + +Code Examples: + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cpp + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cpp + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cpp -o turtle_tf2_broadcaster.cpp + +Language: unknown +curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/turtle_tf2_broadcaster.cpp -o turtle_tf2_broadcaster.cpp + +Language: unknown +#include#include#include#include#include"geometry_msgs/msg/transform_stamped.hpp"#include"rclcpp/rclcpp.hpp"#include"tf2/LinearMath/Quaternion.h"#include"tf2_ros/transform_broadcaster.h"#include"turtlesim/msg/pose.hpp"classFramePublisher:publicrclcpp::Node{public:FramePublisher():Node("turtle_tf2_frame_publisher"){// Declare and acquire `turtlename` parameterturtlename_=this->declare_parameter("turtlename","turtle");// Initialize the transform broadcastertf_broadcaster_=std::make_unique(*this);// Subscribe to a turtle{1}{2}/pose topic and call handle_turtle_pose// callback function on each messagestd::ostringstreamstream;stream<<"/"<msg){geometry_msgs::msg::TransformStampedt;// Read message content and assign it to// corresponding tf variablest.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=turtlename_.c_str();// Turtle only exists in 2D, thus we get x and y translation// coordinates from the message and set the z coordinate to 0t.transform.translation.x=msg->x;t.transform.translation.y=msg->y;t.transform.translation.z=0.0;// For the same reason, turtle can only rotate around one axis// and this why we set rotation in x and y to 0 and obtain// rotation in z axis from the messagetf2::Quaternionq;q.setRPY(0,0,msg->theta);t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w();// Send the transformationtf_broadcaster_->sendTransform(t);};subscription_=this->create_subscription(topic_name,10,handle_turtle_pose);}private:rclcpp::Subscription::SharedPtrsubscription_;std::unique_ptrtf_broadcaster_;std::stringturtlename_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +turtlename_=this->declare_parameter("turtlename","turtle"); + +Language: unknown +subscription_=this->create_subscription(topic_name,10,handle_turtle_pose); + +Language: unknown +geometry_msgs::msg::TransformStampedt;// Read message content and assign it to// corresponding tf variablest.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=turtlename_.c_str(); + +Language: unknown +// Turtle only exists in 2D, thus we get x and y translation// coordinates from the message and set the z coordinate to 0t.transform.translation.x=msg->x;t.transform.translation.y=msg->y;t.transform.translation.z=0.0;// For the same reason, turtle can only rotate around one axis// and this why we set rotation in x and y to 0 and obtain// rotation in z axis from the messagetf2::Quaternionq;q.setRPY(0,0,msg->theta);t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w(); + +Language: unknown +// Send the transformationtf_broadcaster_->sendTransform(t); + +Language: unknown +add_executable(turtle_tf2_broadcaster src/turtle_tf2_broadcaster.cpp)ament_target_dependencies(turtle_tf2_broadcastergeometry_msgsrclcpptf2tf2_rosturtlesim) + +Language: unknown +install(TARGETSturtle_tf2_broadcasterDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_cpp',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),]) + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNode + +Language: unknown +Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_cpp',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]), + +Language: unknown +launchlaunch_ros + +Language: unknown +install(DIRECTORY launchDESTINATION share/${PROJECT_NAME}) + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select learning_tf2_cpp + +Language: unknown +colcon build --packages-select learning_tf2_cpp + +Language: unknown +colcon build --merge-install --packages-select learning_tf2_cpp + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +#CMDcall install\setup.bat#Powershell.\install\setup.ps1 + +Language: unknown +ros2 launch learning_tf2_cpp turtle_tf2_demo_launch.py + +Language: unknown +ros2 run turtlesim turtle_teleop_key + +Language: unknown +ros2 run tf2_ros tf2_echo world turtle1 + +Language: unknown +At time 1625137663.912474878- Translation: [5.276, 7.930, 0.000]- Rotation: in Quaternion [0.000, 0.000, 0.934, -0.357]At time 1625137664.950813527- Translation: [3.750, 6.563, 0.000]- Rotation: in Quaternion [0.000, 0.000, 0.934, -0.357]At time 1625137665.906280726- Translation: [2.320, 5.282, 0.000]- Rotation: in Quaternion [0.000, 0.000, 0.934, -0.357]At time 1625137666.850775673- Translation: [2.153, 5.133, 0.000]- Rotation: in Quaternion [0.000, 0.000, -0.365, 0.931] diff --git "a/exported_docs/ros2/Writing_a_listener_(Python)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_listener_(Python)\357\203\201.txt" new file mode 100644 index 0000000..01bc392 --- /dev/null +++ "b/exported_docs/ros2/Writing_a_listener_(Python)\357\203\201.txt" @@ -0,0 +1,75 @@ +Title: Writing a listener (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Listener-Py.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a listener (Python)Goal:Learn how to use tf2 to get access to frame transformations.Tutorial level:IntermediateTime:10 minutesContentsBackgroundPrerequisitesTasks1 Write the listener node2 Update the launch file3 Build4 RunSummaryBackgroundIn previous tutorials we created a tf2 broadcaster to publish the pose of a turtle to tf2.In this tutorial we’ll create a tf2 listener to start using tf2.PrerequisitesThis tutorial assumes you have completed thetf2 static broadcaster tutorial (Python)andtf2 broadcaster tutorial (Python). +In the previous tutorial, we created alearning_tf2_pypackage, which is where we will continue working from.Tasks1 Write the listener nodeLet’s first create the source files. +Go to thelearning_tf2_pypackage we created in the previous tutorial. +Inside thesrc/learning_tf2_py/learning_tf2_pydirectory download the example listener code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.pywget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.pyIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py -o turtle_tf2_listener.pyOr in powershell:curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py -o turtle_tf2_listener.pyNow open the file calledturtle_tf2_listener.pyusing your preferred text editor.importmathfromgeometry_msgs.msgimportTwistimportrclpyfromrclpy.nodeimportNodefromtf2_rosimportTransformExceptionfromtf2_ros.bufferimportBufferfromtf2_ros.transform_listenerimportTransformListenerfromturtlesim.srvimportSpawnclassFrameListener(Node):def__init__(self):super().__init__('turtle_tf2_frame_listener')# Declare and acquire `target_frame` parameterself.target_frame=self.declare_parameter('target_frame','turtle1').get_parameter_value().string_valueself.tf_buffer=Buffer()self.tf_listener=TransformListener(self.tf_buffer,self)# Create a client to spawn a turtleself.spawner=self.create_client(Spawn,'spawn')# Boolean values to store the information# if the service for spawning turtle is availableself.turtle_spawning_service_ready=False# if the turtle was successfully spawnedself.turtle_spawned=False# Create turtle2 velocity publisherself.publisher=self.create_publisher(Twist,'turtle2/cmd_vel',1)# Call on_timer function every secondself.timer=self.create_timer(1.0,self.on_timer)defon_timer(self):# Store frame names in variables that will be used to# compute transformationsfrom_frame_rel=self.target_frameto_frame_rel='turtle2'ifself.turtle_spawning_service_ready:ifself.turtle_spawned:# Look up for the transformation between target_frame and turtle2 frames# and send velocity commands for turtle2 to reach target_frametry:t=self.tf_buffer.lookup_transform(to_frame_rel,from_frame_rel,rclpy.time.Time())exceptTransformExceptionasex:self.get_logger().info(f'Could not transform{to_frame_rel}to{from_frame_rel}:{ex}')returnmsg=Twist()scale_rotation_rate=1.0msg.angular.z=scale_rotation_rate*math.atan2(t.transform.translation.y,t.transform.translation.x)scale_forward_speed=0.5msg.linear.x=scale_forward_speed*math.sqrt(t.transform.translation.x**2+t.transform.translation.y**2)self.publisher.publish(msg)else:ifself.result.done():self.get_logger().info(f'Successfully spawned{self.result.result().name}')self.turtle_spawned=Trueelse:self.get_logger().info('Spawn is not finished')else:ifself.spawner.service_is_ready():# Initialize request with turtle name and coordinates# Note that x, y and theta are defined as floats in turtlesim/srv/Spawnrequest=Spawn.Request()request.name='turtle2'request.x=float(4)request.y=float(2)request.theta=float(0)# Call requestself.result=self.spawner.call_async(request)self.turtle_spawning_service_ready=Trueelse:# Check if the service is readyself.get_logger().info('Service is not ready')defmain():rclpy.init()node=FrameListener()try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown()1.1 Examine the codeTo understand how the service behind spawning turtle works, please refer towriting a simple service and client (Python)tutorial.Now, let’s take a look at the code that is relevant to get access to frame transformations. +Thetf2_rospackage provides an implementation of aTransformListenerto help make the task of receiving transforms easier.fromtf2_ros.transform_listenerimportTransformListenerHere, we create aTransformListenerobject. +Once the listener is created, it starts receiving tf2 transformations over the wire, and buffers them for up to 10 seconds.self.tf_listener=TransformListener(self.tf_buffer,self)Finally, we query the listener for a specific transformation. +We calllookup_transformmethod with following arguments:Target frameSource frameThe time at which we want to transformProvidingrclpy.time.Time()will just get us the latest available transform. +All this is wrapped in a try-except block to handle possible exceptions.t=self.tf_buffer.lookup_transform(to_frame_rel,from_frame_rel,rclpy.time.Time())1.2 Add an entry pointTo allow theros2runcommand to run your node, you must add the entry point tosetup.py(located in thesrc/learning_tf2_pydirectory).Add the following line between the'console_scripts':brackets:'turtle_tf2_listener = learning_tf2_py.turtle_tf2_listener:main',2 Update the launch fileOpen the launch file calledturtle_tf2_demo_launch.pyin thesrc/learning_tf2_py/launchdirectory with your text editor, add two new nodes to the launch description, add a launch argument, and add the imports. +The resulting file should look like:fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),DeclareLaunchArgument('target_frame',default_value='turtle1',description='Target frame name.'),Node(package='learning_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster2',parameters=[{'turtlename':'turtle2'}]),Node(package='learning_tf2_py',executable='turtle_tf2_listener',name='listener',parameters=[{'target_frame':LaunchConfiguration('target_frame')}]),])This will declare atarget_framelaunch argument, start a broadcaster for second turtle that we will spawn and listener that will subscribe to those transformations.3 BuildRunrosdepin the root of your workspace to check for missing dependencies.LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfStill in the root of your workspace, build your package:LinuxmacOSWindowscolcon build --packages-select learning_tf2_pycolcon build --packages-select learning_tf2_pycolcon build --merge-install --packages-select learning_tf2_pyOpen a new terminal, navigate to the root of your workspace, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bash#CMDcall install\setup.bat#Powershell.\install\setup.ps14 RunNow you’re ready to start your full turtle demo:ros2 launch learning_tf2_py turtle_tf2_demo_launch.pyYou should see the turtle sim with two turtles. +In the second terminal window type the following command:ros2 run turtlesim turtle_teleop_keyTo see if things work, simply drive around the first turtle using the arrow keys (make sure your terminal window is active, not your simulator window), and you’ll see the second turtle following the first one!SummaryIn this tutorial you learned how to use tf2 to get access to frame transformations. +You also have finished writing your own turtlesim demo that you first tried inIntroduction to tf2tutorial. + +Code Examples: + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py -o turtle_tf2_listener.py + +Language: unknown +curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_listener.py -o turtle_tf2_listener.py + +Language: unknown +importmathfromgeometry_msgs.msgimportTwistimportrclpyfromrclpy.nodeimportNodefromtf2_rosimportTransformExceptionfromtf2_ros.bufferimportBufferfromtf2_ros.transform_listenerimportTransformListenerfromturtlesim.srvimportSpawnclassFrameListener(Node):def__init__(self):super().__init__('turtle_tf2_frame_listener')# Declare and acquire `target_frame` parameterself.target_frame=self.declare_parameter('target_frame','turtle1').get_parameter_value().string_valueself.tf_buffer=Buffer()self.tf_listener=TransformListener(self.tf_buffer,self)# Create a client to spawn a turtleself.spawner=self.create_client(Spawn,'spawn')# Boolean values to store the information# if the service for spawning turtle is availableself.turtle_spawning_service_ready=False# if the turtle was successfully spawnedself.turtle_spawned=False# Create turtle2 velocity publisherself.publisher=self.create_publisher(Twist,'turtle2/cmd_vel',1)# Call on_timer function every secondself.timer=self.create_timer(1.0,self.on_timer)defon_timer(self):# Store frame names in variables that will be used to# compute transformationsfrom_frame_rel=self.target_frameto_frame_rel='turtle2'ifself.turtle_spawning_service_ready:ifself.turtle_spawned:# Look up for the transformation between target_frame and turtle2 frames# and send velocity commands for turtle2 to reach target_frametry:t=self.tf_buffer.lookup_transform(to_frame_rel,from_frame_rel,rclpy.time.Time())exceptTransformExceptionasex:self.get_logger().info(f'Could not transform{to_frame_rel}to{from_frame_rel}:{ex}')returnmsg=Twist()scale_rotation_rate=1.0msg.angular.z=scale_rotation_rate*math.atan2(t.transform.translation.y,t.transform.translation.x)scale_forward_speed=0.5msg.linear.x=scale_forward_speed*math.sqrt(t.transform.translation.x**2+t.transform.translation.y**2)self.publisher.publish(msg)else:ifself.result.done():self.get_logger().info(f'Successfully spawned{self.result.result().name}')self.turtle_spawned=Trueelse:self.get_logger().info('Spawn is not finished')else:ifself.spawner.service_is_ready():# Initialize request with turtle name and coordinates# Note that x, y and theta are defined as floats in turtlesim/srv/Spawnrequest=Spawn.Request()request.name='turtle2'request.x=float(4)request.y=float(2)request.theta=float(0)# Call requestself.result=self.spawner.call_async(request)self.turtle_spawning_service_ready=Trueelse:# Check if the service is readyself.get_logger().info('Service is not ready')defmain():rclpy.init()node=FrameListener()try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown() + +Language: unknown +fromtf2_ros.transform_listenerimportTransformListener + +Language: unknown +self.tf_listener=TransformListener(self.tf_buffer,self) + +Language: unknown +t=self.tf_buffer.lookup_transform(to_frame_rel,from_frame_rel,rclpy.time.Time()) + +Language: unknown +'turtle_tf2_listener = learning_tf2_py.turtle_tf2_listener:main', + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch.actionsimportDeclareLaunchArgumentfromlaunch.substitutionsimportLaunchConfigurationfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename':'turtle1'}]),DeclareLaunchArgument('target_frame',default_value='turtle1',description='Target frame name.'),Node(package='learning_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster2',parameters=[{'turtlename':'turtle2'}]),Node(package='learning_tf2_py',executable='turtle_tf2_listener',name='listener',parameters=[{'target_frame':LaunchConfiguration('target_frame')}]),]) + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --merge-install --packages-select learning_tf2_py + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +#CMDcall install\setup.bat#Powershell.\install\setup.ps1 + +Language: unknown +ros2 launch learning_tf2_py turtle_tf2_demo_launch.py + +Language: unknown +ros2 run turtlesim turtle_teleop_key diff --git "a/exported_docs/ros2/Writing_a_simple_publisher_and_subscriber_(C++)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_simple_publisher_and_subscriber_(C++)\357\203\201.txt" new file mode 100644 index 0000000..c83d13a --- /dev/null +++ "b/exported_docs/ros2/Writing_a_simple_publisher_and_subscriber_(C++)\357\203\201.txt" @@ -0,0 +1,141 @@ +Title: Writing a simple publisher and subscriber (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a simple publisher and subscriber (C++)Goal:Create and run a publisher and subscriber node using C++.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the publisher node3 Write the subscriber node4 Build and runSummaryNext stepsRelated contentBackgroundNodesare executable processes that communicate over the ROS graph. +In this tutorial, the nodes will pass information in the form of string messages to each other over atopic. +The example used here is a simple “talker” and “listener” system; one node publishes data and the other subscribes to the topic so it can receive that data.The code used in these examples can be foundhere.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Navigate into theros2_wsdirectory created in aprevious tutorial.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +So, navigate intoros2_ws/src, and run the package creation command:ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_pubsubYour terminal will return a message verifying the creation of your packagecpp_pubsuband all its necessary files and folders.Navigate intoros2_ws/src/cpp_pubsub/src. +Recall that this is the directory in any CMake package where the source files containing executables belong.2 Write the publisher nodeDownload the example talker code by entering the following command:LinuxmacOSWindowswget -O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cppwget -O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cppIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp -o publisher_lambda_function.cppOr in powershell:curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp -o publisher_lambda_function.cppNow there will be a new file namedpublisher_lambda_function.cpp. +Open the file using your preferred text editor.#include#include#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;/* This example creates a subclass of Node and uses a fancy C++11 lambda* function to shorten the callback syntax, at the expense of making the* code somewhat more difficult to understand at first glance. */classMinimalPublisher:publicrclcpp::Node{public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing: '%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);}private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;size_tcount_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.1 Examine the codeThe top of the code includes the standard C++ headers you will be using. +After the standard C++ headers is therclcpp/rclcpp.hppinclude which allows you to use the most common pieces of the ROS 2 system. +Last isstd_msgs/msg/string.hpp, which includes the built-in message type you will use to publish data.#include#include#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;These lines represent the node’s dependencies. +Recall that dependencies have to be added topackage.xmlandCMakeLists.txt, which you’ll do in the next section.The next line creates the node classMinimalPublisherby inheriting fromrclcpp::Node. +Everythisin the code is referring to the node.classMinimalPublisher:publicrclcpp::NodeThe public constructor names the nodeminimal_publisherand initializescount_to 0. +Inside the constructor, the publisher is initialized with theStringmessage type, the topic nametopic, and the required queue size to limit messages in the event of a backup. +Next, alambda functioncalledtimer_callbackis declared. +It performs a by-reference capture of the current objectthis, takes no input arguments and returns void. +Thetimer_callbackfunction creates a new message of typeString, sets its data with the desired string and publishes it. +TheRCLCPP_INFOmacro ensures every published message is printed to the console. +At last,timer_is initialized, which causes thetimer_callbackfunction to be executed twice a second.public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing: '%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);}In the bottom of the class is the declaration of the timer, publisher, and counter fields.private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;size_tcount_;Following theMinimalPublisherclass ismain, where the node actually executes.rclcpp::initinitializes ROS 2, andrclcpp::spinstarts processing data from the node, including callbacks from the timer.intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}2.2 Add dependenciesNavigate one level back to theros2_ws/src/cpp_pubsubdirectory, where theCMakeLists.txtandpackage.xmlfiles have been created for you.Openpackage.xmlwith your text editor.As mentioned in theprevious tutorial, make sure to fill in the,andtags:Examplesofminimalpublisher/subscriberusingrclcppYourNameApache-2.0Add a new line after theament_cmakebuildtool dependency and paste the following dependencies corresponding to your node’s include statements:rclcppstd_msgsThis declares the package needsrclcppandstd_msgswhen its code is built and executed.Make sure to save the file.2.3 CMakeLists.txtNow open theCMakeLists.txtfile. +Below the existing dependencyfind_package(ament_cmakeREQUIRED), add the lines:find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)After that, add the executable and name ittalkerso you can run your node usingros2run:add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)Finally, add theinstall(TARGETS...)section soros2runcan find your executable:install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})You can clean up yourCMakeLists.txtby removing some unnecessary sections and comments, so it looks like this:cmake_minimum_required(VERSION 3.5)project(cpp_pubsub)#DefaulttoC++14if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14)endif()if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)endif()find_package(ament_cmake REQUIRED)find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})ament_package()You could build your package now, source the local setup files, and run it, but let’s create the subscriber node first so you can see the full system at work.3 Write the subscriber nodeReturn toros2_ws/src/cpp_pubsub/srcto create the next node. +Enter the following code in your terminal:LinuxmacOSWindowswget -O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cppwget -O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cppIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp -o subscriber_lambda_function.cppOr in powershell:curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp -o subscriber_lambda_function.cppCheck to ensure that these files exist:publisher_lambda_function.cpp subscriber_lambda_function.cppOpen thesubscriber_lambda_function.cppwith your text editor.#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"classMinimalSubscriber:publicrclcpp::Node{public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)->void{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());};subscription_=this->create_subscription("topic",10,topic_callback);}private:rclcpp::Subscription::SharedPtrsubscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;}3.1 Examine the codeThe subscriber node’s code is nearly identical to the publisher’s. +Now the node is namedminimal_subscriber, and the constructor uses the node’screate_subscriptionfunction to execute the callback.There is no timer because the subscriber simply responds whenever data is published to thetopictopic.Thetopic_callbackfunction receives the string message data published over the topic, and simply writes it to the console using theRCLCPP_INFOmacro.Recall from thetopic tutorialthat the topic name and message type used by the publisher and subscriber must match to allow them to communicate.public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)->void{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());};subscription_=this->create_subscription("topic",10,topic_callback);}The only field declaration in this class is the subscription.private:rclcpp::Subscription::SharedPtrsubscription_;Themainfunction is exactly the same, except now it spins theMinimalSubscribernode. +For the publisher node, spinning meant starting the timer, but for the subscriber it simply means preparing to receive messages whenever they come.Since this node has the same dependencies as the publisher node, there’s nothing new to add topackage.xml.3.2 CMakeLists.txtReopenCMakeLists.txtand add the executable and target for the subscriber node below the publisher’s entries.add_executable(listenersrc/subscriber_lambda_function.cpp)ament_target_dependencies(listenerrclcppstd_msgs)install(TARGETStalkerlistenerDESTINATIONlib/${PROJECT_NAME})Make sure to save the file, and then your pub/sub system should be ready.4 Build and runYou likely already have therclcppandstd_msgspackages installed as part of your ROS 2 system. +It’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Still in the root of your workspace,ros2_ws, build your new package:LinuxmacOSWindowscolcon build --packages-select cpp_pubsubcolcon build --packages-select cpp_pubsubcolcon build --merge-install --packages-select cpp_pubsubOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bashcall install/setup.batNow run the talker node:ros2 run cpp_pubsub talkerThe terminal should start publishing info messages every 0.5 seconds, like so:[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4"Open another terminal, source the setup files from insideros2_wsagain, and then start the listener node:ros2 run cpp_pubsub listenerThe listener will start printing messages to the console, starting at whatever message count the publisher is on at that time, like so:[INFO] [minimal_subscriber]: I heard: "Hello World: 10"[INFO] [minimal_subscriber]: I heard: "Hello World: 11"[INFO] [minimal_subscriber]: I heard: "Hello World: 12"[INFO] [minimal_subscriber]: I heard: "Hello World: 13"[INFO] [minimal_subscriber]: I heard: "Hello World: 14"EnterCtrl+Cin each terminal to stop the nodes from spinning.SummaryYou created two nodes to publish and subscribe to data over a topic. +Before compiling and running them, you added their dependencies and executables to the package configuration files.Next stepsNext you’ll create another simple ROS 2 package using the service/client model. +Again, you can choose to write it in eitherC++orPython.Related contentThere are several ways you could write a publisher and subscriber in C++; check out theminimal_publisherandminimal_subscriberpackages in theros2/examplesrepo. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_pubsub + +Language: unknown +wget -O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp + +Language: unknown +wget -O publisher_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp -o publisher_lambda_function.cpp + +Language: unknown +curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_publisher/lambda.cpp -o publisher_lambda_function.cpp + +Language: unknown +#include#include#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals;/* This example creates a subclass of Node and uses a fancy C++11 lambda* function to shorten the callback syntax, at the expense of making the* code somewhat more difficult to understand at first glance. */classMinimalPublisher:publicrclcpp::Node{public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing: '%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);}private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;size_tcount_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +#include#include#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"usingnamespacestd::chrono_literals; + +Language: unknown +classMinimalPublisher:publicrclcpp::Node + +Language: unknown +public:MinimalPublisher():Node("minimal_publisher"),count_(0){publisher_=this->create_publisher("topic",10);autotimer_callback=[this]()->void{automessage=std_msgs::msg::String();message.data="Hello, world! "+std::to_string(this->count_++);RCLCPP_INFO(this->get_logger(),"Publishing: '%s'",message.data.c_str());this->publisher_->publish(message);};timer_=this->create_wall_timer(500ms,timer_callback);} + +Language: unknown +private:rclcpp::TimerBase::SharedPtrtimer_;rclcpp::Publisher::SharedPtrpublisher_;size_tcount_; + +Language: unknown +intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +Examplesofminimalpublisher/subscriberusingrclcppYourNameApache-2.0 + +Language: unknown +rclcppstd_msgs + +Language: unknown +find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED) + +Language: unknown +add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs) + +Language: unknown +install(TARGETStalkerDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +cmake_minimum_required(VERSION 3.5)project(cpp_pubsub)#DefaulttoC++14if(NOT CMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD 14)endif()if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)endif()find_package(ament_cmake REQUIRED)find_package(rclcpp REQUIRED)find_package(std_msgs REQUIRED)add_executable(talker src/publisher_lambda_function.cpp)ament_target_dependencies(talker rclcpp std_msgs)install(TARGETStalkerDESTINATION lib/${PROJECT_NAME})ament_package() + +Language: unknown +wget -O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp + +Language: unknown +wget -O subscriber_lambda_function.cpp https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp -o subscriber_lambda_function.cpp + +Language: unknown +curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclcpp/topics/minimal_subscriber/lambda.cpp -o subscriber_lambda_function.cpp + +Language: unknown +publisher_lambda_function.cpp subscriber_lambda_function.cpp + +Language: unknown +#include#include"rclcpp/rclcpp.hpp"#include"std_msgs/msg/string.hpp"classMinimalSubscriber:publicrclcpp::Node{public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)->void{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());};subscription_=this->create_subscription("topic",10,topic_callback);}private:rclcpp::Subscription::SharedPtrsubscription_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_shared());rclcpp::shutdown();return0;} + +Language: unknown +public:MinimalSubscriber():Node("minimal_subscriber"){autotopic_callback=[this](std_msgs::msg::String::UniquePtrmsg)->void{RCLCPP_INFO(this->get_logger(),"I heard: '%s'",msg->data.c_str());};subscription_=this->create_subscription("topic",10,topic_callback);} + +Language: unknown +private:rclcpp::Subscription::SharedPtrsubscription_; + +Language: unknown +add_executable(listenersrc/subscriber_lambda_function.cpp)ament_target_dependencies(listenerrclcppstd_msgs)install(TARGETStalkerlistenerDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select cpp_pubsub + +Language: unknown +colcon build --packages-select cpp_pubsub + +Language: unknown +colcon build --merge-install --packages-select cpp_pubsub + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run cpp_pubsub talker + +Language: unknown +[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4" + +Language: unknown +ros2 run cpp_pubsub listener + +Language: unknown +[INFO] [minimal_subscriber]: I heard: "Hello World: 10"[INFO] [minimal_subscriber]: I heard: "Hello World: 11"[INFO] [minimal_subscriber]: I heard: "Hello World: 12"[INFO] [minimal_subscriber]: I heard: "Hello World: 13"[INFO] [minimal_subscriber]: I heard: "Hello World: 14" diff --git "a/exported_docs/ros2/Writing_a_simple_publisher_and_subscriber_(Python)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_simple_publisher_and_subscriber_(Python)\357\203\201.txt" new file mode 100644 index 0000000..e833051 --- /dev/null +++ "b/exported_docs/ros2/Writing_a_simple_publisher_and_subscriber_(Python)\357\203\201.txt" @@ -0,0 +1,139 @@ +Title: Writing a simple publisher and subscriber (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a simple publisher and subscriber (Python)Goal:Create and run a publisher and subscriber node using Python.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the publisher node3 Write the subscriber node4 Build and runSummaryNext stepsRelated contentBackgroundIn this tutorial, you will createnodesthat pass information in the form of string messages to each other over atopic. +The example used here is a simple “talker” and “listener” system; +one node publishes data and the other subscribes to the topic so it can receive that data.The code used in these examples can be foundhere.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.A basic understanding of Python is recommended, but not entirely necessary.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Navigate into theros2_wsdirectory created in aprevious tutorial.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +So, navigate intoros2_ws/src, and run the package creation command:ros2 pkg create --build-type ament_python --license Apache-2.0 py_pubsubYour terminal will return a message verifying the creation of your packagepy_pubsuband all its necessary files and folders.2 Write the publisher nodeNavigate intoros2_ws/src/py_pubsub/py_pubsub. +Recall that this directory is aPython packagewith the same name as the ROS 2 package it’s nested in.Download the example talker code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.pywget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.pyIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py -o publisher_member_function.pyOr in powershell:curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py -o publisher_member_function.pyNow there will be a new file namedpublisher_member_function.pyadjacent to__init__.py.Open the file using your preferred text editor.importrclpyfromrclpy.nodeimportNodefromstd_msgs.msgimportStringclassMinimalPublisher(Node):def__init__(self):super().__init__('minimal_publisher')self.publisher_=self.create_publisher(String,'topic',10)timer_period=0.5# secondsself.timer=self.create_timer(timer_period,self.timer_callback)self.i=0deftimer_callback(self):msg=String()msg.data='Hello World:%d'%self.iself.publisher_.publish(msg)self.get_logger().info('Publishing: "%s"'%msg.data)self.i+=1defmain(args=None):rclpy.init(args=args)minimal_publisher=MinimalPublisher()rclpy.spin(minimal_publisher)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)minimal_publisher.destroy_node()rclpy.shutdown()if__name__=='__main__':main()2.1 Examine the codeThe first lines of code after the comments importrclpyso itsNodeclass can be used.importrclpyfromrclpy.nodeimportNodeThe next statement imports the built-in string message type that the node uses to structure the data that it passes on the topic.fromstd_msgs.msgimportStringThese lines represent the node’s dependencies. +Recall that dependencies have to be added topackage.xml, which you’ll do in the next section.Next, theMinimalPublisherclass is created, which inherits from (or is a subclass of)Node.classMinimalPublisher(Node):Following is the definition of the class’s constructor.super().__init__calls theNodeclass’s constructor and gives it your node name, in this caseminimal_publisher.create_publisherdeclares that the node publishes messages of typeString(imported from thestd_msgs.msgmodule), over a topic namedtopic, and that the “queue size” is 10. +Queue size is a required QoS (quality of service) setting that limits the amount of queued messages if a subscriber is not receiving them fast enough.Next, a timer is created with a callback to execute every 0.5 seconds.self.iis a counter used in the callback.def__init__(self):super().__init__('minimal_publisher')self.publisher_=self.create_publisher(String,'topic',10)timer_period=0.5# secondsself.timer=self.create_timer(timer_period,self.timer_callback)self.i=0timer_callbackcreates a message with the counter value appended, and publishes it to the console withget_logger().info.deftimer_callback(self):msg=String()msg.data='Hello World:%d'%self.iself.publisher_.publish(msg)self.get_logger().info('Publishing: "%s"'%msg.data)self.i+=1Lastly, the main function is defined.defmain(args=None):rclpy.init(args=args)minimal_publisher=MinimalPublisher()rclpy.spin(minimal_publisher)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)minimal_publisher.destroy_node()rclpy.shutdown()First therclpylibrary is initialized, then the node is created, and then it “spins” the node so its callbacks are called.2.2 Add dependenciesNavigate one level back to theros2_ws/src/py_pubsubdirectory, where thesetup.py,setup.cfg, andpackage.xmlfiles have been created for you.Openpackage.xmlwith your text editor.As mentioned in theprevious tutorial, make sure to fill in the,andtags:Examplesofminimalpublisher/subscriberusingrclpyYourNameApache-2.0After the lines above, add the following dependencies corresponding to your node’s import statements:rclpystd_msgsThis declares the package needsrclpyandstd_msgswhen its code is executed.Make sure to save the file.2.3 Add an entry pointOpen thesetup.pyfile. +Again, match themaintainer,maintainer_email,descriptionandlicensefields to yourpackage.xml:maintainer='YourName',maintainer_email='you@email.com',description='Examples of minimal publisher/subscriber using rclpy',license='Apache-2.0',Add the following line within theconsole_scriptsbrackets of theentry_pointsfield:entry_points={'console_scripts':['talker = py_pubsub.publisher_member_function:main',],},Don’t forget to save.2.4 Check setup.cfgThe contents of thesetup.cfgfile should be correctly populated automatically, like so:[develop]script_dir=$base/lib/py_pubsub[install]install_scripts=$base/lib/py_pubsubThis is simply telling setuptools to put your executables inlib, becauseros2runwill look for them there.You could build your package now, source the local setup files, and run it, but let’s create the subscriber node first so you can see the full system at work.3 Write the subscriber nodeReturn toros2_ws/src/py_pubsub/py_pubsubto create the next node. +Enter the following code in your terminal:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.pywget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.pyIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py -o subscriber_member_function.pyOr in powershell:curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py -o subscriber_member_function.pyNow the directory should have these files:__init__.py publisher_member_function.py subscriber_member_function.py3.1 Examine the codeOpen thesubscriber_member_function.pywith your text editor.importrclpyfromrclpy.nodeimportNodefromstd_msgs.msgimportStringclassMinimalSubscriber(Node):def__init__(self):super().__init__('minimal_subscriber')self.subscription=self.create_subscription(String,'topic',self.listener_callback,10)self.subscription# prevent unused variable warningdeflistener_callback(self,msg):self.get_logger().info('I heard: "%s"'%msg.data)defmain(args=None):rclpy.init(args=args)minimal_subscriber=MinimalSubscriber()rclpy.spin(minimal_subscriber)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)minimal_subscriber.destroy_node()rclpy.shutdown()if__name__=='__main__':main()The subscriber node’s code is nearly identical to the publisher’s. +The constructor creates a subscriber with the same arguments as the publisher. +Recall from thetopics tutorialthat the topic name and message type used by the publisher and subscriber must match to allow them to communicate.self.subscription=self.create_subscription(String,'topic',self.listener_callback,10)The subscriber’s constructor and callback don’t include any timer definition, because it doesn’t need one. +Its callback gets called as soon as it receives a message.The callback definition simply prints an info message to the console, along with the data it received. +Recall that the publisher definesmsg.data='HelloWorld:%d'%self.ideflistener_callback(self,msg):self.get_logger().info('I heard: "%s"'%msg.data)Themaindefinition is almost exactly the same, replacing the creation and spinning of the publisher with the subscriber.minimal_subscriber=MinimalSubscriber()rclpy.spin(minimal_subscriber)Since this node has the same dependencies as the publisher, there’s nothing new to add topackage.xml. +Thesetup.cfgfile can also remain untouched.3.2 Add an entry pointReopensetup.pyand add the entry point for the subscriber node below the publisher’s entry point. +Theentry_pointsfield should now look like this:entry_points={'console_scripts':['talker = py_pubsub.publisher_member_function:main','listener = py_pubsub.subscriber_member_function:main',],},Make sure to save the file, and then your pub/sub system should be ready.4 Build and runYou likely already have therclpyandstd_msgspackages installed as part of your ROS 2 system. +It’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Still in the root of your workspace,ros2_ws, build your new package:LinuxmacOSWindowscolcon build --packages-select py_pubsubcolcon build --packages-select py_pubsubcolcon build --merge-install --packages-select py_pubsubOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the talker node:ros2 run py_pubsub talkerThe terminal should start publishing info messages every 0.5 seconds, like so:[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4"...Open another terminal, source the setup files from insideros2_wsagain, and then start the listener node:ros2 run py_pubsub listenerThe listener will start printing messages to the console, starting at whatever message count the publisher is on at that time, like so:[INFO] [minimal_subscriber]: I heard: "Hello World: 10"[INFO] [minimal_subscriber]: I heard: "Hello World: 11"[INFO] [minimal_subscriber]: I heard: "Hello World: 12"[INFO] [minimal_subscriber]: I heard: "Hello World: 13"[INFO] [minimal_subscriber]: I heard: "Hello World: 14"EnterCtrl+Cin each terminal to stop the nodes from spinning.SummaryYou created two nodes to publish and subscribe to data over a topic. +Before running them, you added their dependencies and entry points to the package configuration files.Next stepsNext you’ll create another simple ROS 2 package using the service/client model. +Again, you can choose to write it in eitherC++orPython.Related contentThere are several ways you could write a publisher and subscriber in Python; check out theminimal_publisherandminimal_subscriberpackages in theros2/examplesrepo. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 py_pubsub + +Language: unknown +wget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py + +Language: unknown +wget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py -o publisher_member_function.py + +Language: unknown +curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py -o publisher_member_function.py + +Language: unknown +importrclpyfromrclpy.nodeimportNodefromstd_msgs.msgimportStringclassMinimalPublisher(Node):def__init__(self):super().__init__('minimal_publisher')self.publisher_=self.create_publisher(String,'topic',10)timer_period=0.5# secondsself.timer=self.create_timer(timer_period,self.timer_callback)self.i=0deftimer_callback(self):msg=String()msg.data='Hello World:%d'%self.iself.publisher_.publish(msg)self.get_logger().info('Publishing: "%s"'%msg.data)self.i+=1defmain(args=None):rclpy.init(args=args)minimal_publisher=MinimalPublisher()rclpy.spin(minimal_publisher)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)minimal_publisher.destroy_node()rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +importrclpyfromrclpy.nodeimportNode + +Language: unknown +fromstd_msgs.msgimportString + +Language: unknown +classMinimalPublisher(Node): + +Language: unknown +def__init__(self):super().__init__('minimal_publisher')self.publisher_=self.create_publisher(String,'topic',10)timer_period=0.5# secondsself.timer=self.create_timer(timer_period,self.timer_callback)self.i=0 + +Language: unknown +deftimer_callback(self):msg=String()msg.data='Hello World:%d'%self.iself.publisher_.publish(msg)self.get_logger().info('Publishing: "%s"'%msg.data)self.i+=1 + +Language: unknown +defmain(args=None):rclpy.init(args=args)minimal_publisher=MinimalPublisher()rclpy.spin(minimal_publisher)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)minimal_publisher.destroy_node()rclpy.shutdown() + +Language: unknown +Examplesofminimalpublisher/subscriberusingrclpyYourNameApache-2.0 + +Language: unknown +rclpystd_msgs + +Language: unknown +maintainer='YourName',maintainer_email='you@email.com',description='Examples of minimal publisher/subscriber using rclpy',license='Apache-2.0', + +Language: unknown +entry_points={'console_scripts':['talker = py_pubsub.publisher_member_function:main',],}, + +Language: unknown +[develop]script_dir=$base/lib/py_pubsub[install]install_scripts=$base/lib/py_pubsub + +Language: unknown +wget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py + +Language: unknown +wget https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py -o subscriber_member_function.py + +Language: unknown +curl https://raw.githubusercontent.com/ros2/examples/jazzy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py -o subscriber_member_function.py + +Language: unknown +__init__.py publisher_member_function.py subscriber_member_function.py + +Language: unknown +importrclpyfromrclpy.nodeimportNodefromstd_msgs.msgimportStringclassMinimalSubscriber(Node):def__init__(self):super().__init__('minimal_subscriber')self.subscription=self.create_subscription(String,'topic',self.listener_callback,10)self.subscription# prevent unused variable warningdeflistener_callback(self,msg):self.get_logger().info('I heard: "%s"'%msg.data)defmain(args=None):rclpy.init(args=args)minimal_subscriber=MinimalSubscriber()rclpy.spin(minimal_subscriber)# Destroy the node explicitly# (optional - otherwise it will be done automatically# when the garbage collector destroys the node object)minimal_subscriber.destroy_node()rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +self.subscription=self.create_subscription(String,'topic',self.listener_callback,10) + +Language: unknown +deflistener_callback(self,msg):self.get_logger().info('I heard: "%s"'%msg.data) + +Language: unknown +minimal_subscriber=MinimalSubscriber()rclpy.spin(minimal_subscriber) + +Language: unknown +entry_points={'console_scripts':['talker = py_pubsub.publisher_member_function:main','listener = py_pubsub.subscriber_member_function:main',],}, + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select py_pubsub + +Language: unknown +colcon build --packages-select py_pubsub + +Language: unknown +colcon build --merge-install --packages-select py_pubsub + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run py_pubsub talker + +Language: unknown +[INFO] [minimal_publisher]: Publishing: "Hello World: 0"[INFO] [minimal_publisher]: Publishing: "Hello World: 1"[INFO] [minimal_publisher]: Publishing: "Hello World: 2"[INFO] [minimal_publisher]: Publishing: "Hello World: 3"[INFO] [minimal_publisher]: Publishing: "Hello World: 4"... + +Language: unknown +ros2 run py_pubsub listener + +Language: unknown +[INFO] [minimal_subscriber]: I heard: "Hello World: 10"[INFO] [minimal_subscriber]: I heard: "Hello World: 11"[INFO] [minimal_subscriber]: I heard: "Hello World: 12"[INFO] [minimal_subscriber]: I heard: "Hello World: 13"[INFO] [minimal_subscriber]: I heard: "Hello World: 14" diff --git "a/exported_docs/ros2/Writing_a_simple_service_and_client_(C++)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_simple_service_and_client_(C++)\357\203\201.txt" new file mode 100644 index 0000000..fac71c9 --- /dev/null +++ "b/exported_docs/ros2/Writing_a_simple_service_and_client_(C++)\357\203\201.txt" @@ -0,0 +1,108 @@ +Title: Writing a simple service and client (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Service-And-Client.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a simple service and client (C++)Goal:Create and run service and client nodes using C++.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the service node3 Write the client node4 Build and runSummaryNext stepsRelated contentBackgroundWhennodescommunicate usingservices, the node that sends a request for data is called the client node, and the one that responds to the request is the service node. +The structure of the request and response is determined by a.srvfile.The example used here is a simple integer addition system; one node requests the sum of two integers, and the other responds with the result.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Navigate into theros2_wsdirectory created in aprevious tutorial.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +Navigate intoros2_ws/srcand create a new package:ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_srvcli --dependencies rclcpp example_interfacesYour terminal will return a message verifying the creation of your packagecpp_srvcliand all its necessary files and folders.The--dependenciesargument will automatically add the necessary dependency lines topackage.xmlandCMakeLists.txt.example_interfacesis the package that includesthe .srv fileyou will need to structure your requests and responses:int64 aint64 b---int64 sumThe first two lines are the parameters of the request, and below the dashes is the response.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xmlorCMakeLists.txt.As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.C++clientservertutorialYourNameApache-2.02 Write the service nodeInside theros2_ws/src/cpp_srvcli/srcdirectory, create a new file calledadd_two_ints_server.cppand paste the following code within:#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"#includevoidadd(conststd::shared_ptrrequest,std::shared_ptrresponse){response->sum=request->a+request->b;RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Incoming request\na: %ld"" b: %ld",request->a,request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"sending back response: [%ld]",(longint)response->sum);}intmain(intargc,char**argv){rclcpp::init(argc,argv);std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_server");rclcpp::Service::SharedPtrservice=node->create_service("add_two_ints",&add);RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Ready to add two ints.");rclcpp::spin(node);rclcpp::shutdown();}2.1 Examine the codeThe first two#includestatements are your package dependencies.Theaddfunction adds two integers from the request and gives the sum to the response, while notifying the console of its status using logs.voidadd(conststd::shared_ptrrequest,std::shared_ptrresponse){response->sum=request->a+request->b;RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Incoming request\na: %ld"" b: %ld",request->a,request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"sending back response: [%ld]",(longint)response->sum);}Themainfunction accomplishes the following, line by line:Initializes ROS 2 C++ client library:rclcpp::init(argc,argv);Creates a node namedadd_two_ints_server:std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_server");Creates a service namedadd_two_intsfor that node and automatically advertises it over the networks with the&addmethod:rclcpp::Service::SharedPtrservice=node->create_service("add_two_ints",&add);Prints a log message when it’s ready:RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Ready to add two ints.");Spins the node, making the service available.rclcpp::spin(node);2.2 Add executableTheadd_executablemacro generates an executable you can run usingros2run. +Add the following code block toCMakeLists.txtto create an executable namedserver:add_executable(server src/add_two_ints_server.cpp)ament_target_dependencies(server rclcpp example_interfaces)Soros2runcan find the executable, add the following lines to the end of the file, right beforeament_package():install(TARGETSserverDESTINATION lib/${PROJECT_NAME})You could build your package now, source the local setup files, and run it, but let’s create the client node first so you can see the full system at work.3 Write the client nodeInside theros2_ws/src/cpp_srvcli/srcdirectory, create a new file calledadd_two_ints_client.cppand paste the following code within:#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"#include#include#includeusingnamespacestd::chrono_literals;intmain(intargc,char**argv){rclcpp::init(argc,argv);if(argc!=3){RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"usage: add_two_ints_client X Y");return1;}std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_client");rclcpp::Client::SharedPtrclient=node->create_client("add_two_ints");autorequest=std::make_shared();request->a=atoll(argv[1]);request->b=atoll(argv[2]);while(!client->wait_for_service(1s)){if(!rclcpp::ok()){RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Interrupted while waiting for the service. Exiting.");return0;}RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"service not available, waiting again...");}autoresult=client->async_send_request(request);// Wait for the result.if(rclcpp::spin_until_future_complete(node,result)==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Sum: %ld",result.get()->sum);}else{RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Failed to call service add_two_ints");}rclcpp::shutdown();return0;}3.1 Examine the codeSimilar to the service node, the following lines of code create the node and then create the client for that node:std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_client");rclcpp::Client::SharedPtrclient=node->create_client("add_two_ints");Next, the request is created. +Its structure is defined by the.srvfile mentioned earlier.autorequest=std::make_shared();request->a=atoll(argv[1]);request->b=atoll(argv[2]);Thewhileloop gives the client 1 second to search for service nodes in the network. +If it can’t find any, it will continue waiting.RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"service not available, waiting again...");If the client is canceled (e.g. by you enteringCtrl+Cinto the terminal), it will return an error log message stating it was interrupted.RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Interrupted while waiting for the service. Exiting.");Then the client sends its request, and the node spins until it receives its response, or fails.3.2 Add executableReturn toCMakeLists.txtto add the executable and target for the new node. +After removing some unnecessary boilerplate from the automatically generated file, yourCMakeLists.txtshould look like this:cmake_minimum_required(VERSION 3.5)project(cpp_srvcli)find_package(ament_cmake REQUIRED)find_package(rclcpp REQUIRED)find_package(example_interfaces REQUIRED)add_executable(server src/add_two_ints_server.cpp)ament_target_dependencies(server rclcpp example_interfaces)add_executable(client src/add_two_ints_client.cpp)ament_target_dependencies(client rclcpp example_interfaces)install(TARGETSserverclientDESTINATION lib/${PROJECT_NAME})ament_package()4 Build and runIt’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Navigate back to the root of your workspace,ros2_ws, and build your new package:LinuxmacOSWindowscolcon build --packages-select cpp_srvclicolcon build --packages-select cpp_srvclicolcon build --merge-install --packages-select cpp_srvcliOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the service node:ros2 run cpp_srvcli serverThe terminal should return the following message, and then wait:[INFO] [rclcpp]: Ready to add two ints.Open another terminal, source the setup files from insideros2_wsagain. +Start the client node, followed by any two integers separated by a space:ros2 run cpp_srvcli client 2 3If you chose2and3, for example, the client would receive a response like this:[INFO] [rclcpp]: Sum: 5Return to the terminal where your service node is running. +You will see that it published log messages when it received the request and the data it received, and the response it sent back:[INFO] [rclcpp]: Incoming requesta: 2 b: 3[INFO] [rclcpp]: sending back response: [5]EnterCtrl+Cin the server terminal to stop the node from spinning.SummaryYou created two nodes to request and respond to data over a service. +You added their dependencies and executables to the package configuration files so that you could build and run them, and see a service/client system at work.Next stepsIn the last few tutorials you’ve been utilizing interfaces to pass data across topics and services. +Next, you’ll learn how tocreate custom interfaces.Related contentThere are several ways you could write a service and client in C++; check out theminimal_serviceandminimal_clientpackages in theros2/examplesrepo. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_srvcli --dependencies rclcpp example_interfaces + +Language: unknown +int64 aint64 b---int64 sum + +Language: unknown +C++clientservertutorialYourNameApache-2.0 + +Language: unknown +#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"#includevoidadd(conststd::shared_ptrrequest,std::shared_ptrresponse){response->sum=request->a+request->b;RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Incoming request\na: %ld"" b: %ld",request->a,request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"sending back response: [%ld]",(longint)response->sum);}intmain(intargc,char**argv){rclcpp::init(argc,argv);std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_server");rclcpp::Service::SharedPtrservice=node->create_service("add_two_ints",&add);RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Ready to add two ints.");rclcpp::spin(node);rclcpp::shutdown();} + +Language: unknown +voidadd(conststd::shared_ptrrequest,std::shared_ptrresponse){response->sum=request->a+request->b;RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Incoming request\na: %ld"" b: %ld",request->a,request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"sending back response: [%ld]",(longint)response->sum);} + +Language: unknown +rclcpp::init(argc,argv); + +Language: unknown +std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_server"); + +Language: unknown +rclcpp::Service::SharedPtrservice=node->create_service("add_two_ints",&add); + +Language: unknown +RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Ready to add two ints."); + +Language: unknown +rclcpp::spin(node); + +Language: unknown +add_executable(server src/add_two_ints_server.cpp)ament_target_dependencies(server rclcpp example_interfaces) + +Language: unknown +install(TARGETSserverDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +#include"rclcpp/rclcpp.hpp"#include"example_interfaces/srv/add_two_ints.hpp"#include#include#includeusingnamespacestd::chrono_literals;intmain(intargc,char**argv){rclcpp::init(argc,argv);if(argc!=3){RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"usage: add_two_ints_client X Y");return1;}std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_client");rclcpp::Client::SharedPtrclient=node->create_client("add_two_ints");autorequest=std::make_shared();request->a=atoll(argv[1]);request->b=atoll(argv[2]);while(!client->wait_for_service(1s)){if(!rclcpp::ok()){RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Interrupted while waiting for the service. Exiting.");return0;}RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"service not available, waiting again...");}autoresult=client->async_send_request(request);// Wait for the result.if(rclcpp::spin_until_future_complete(node,result)==rclcpp::FutureReturnCode::SUCCESS){RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Sum: %ld",result.get()->sum);}else{RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Failed to call service add_two_ints");}rclcpp::shutdown();return0;} + +Language: unknown +std::shared_ptrnode=rclcpp::Node::make_shared("add_two_ints_client");rclcpp::Client::SharedPtrclient=node->create_client("add_two_ints"); + +Language: unknown +autorequest=std::make_shared();request->a=atoll(argv[1]);request->b=atoll(argv[2]); + +Language: unknown +RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"service not available, waiting again..."); + +Language: unknown +RCLCPP_ERROR(rclcpp::get_logger("rclcpp"),"Interrupted while waiting for the service. Exiting."); + +Language: unknown +cmake_minimum_required(VERSION 3.5)project(cpp_srvcli)find_package(ament_cmake REQUIRED)find_package(rclcpp REQUIRED)find_package(example_interfaces REQUIRED)add_executable(server src/add_two_ints_server.cpp)ament_target_dependencies(server rclcpp example_interfaces)add_executable(client src/add_two_ints_client.cpp)ament_target_dependencies(client rclcpp example_interfaces)install(TARGETSserverclientDESTINATION lib/${PROJECT_NAME})ament_package() + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select cpp_srvcli + +Language: unknown +colcon build --packages-select cpp_srvcli + +Language: unknown +colcon build --merge-install --packages-select cpp_srvcli + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run cpp_srvcli server + +Language: unknown +[INFO] [rclcpp]: Ready to add two ints. + +Language: unknown +ros2 run cpp_srvcli client 2 3 + +Language: unknown +[INFO] [rclcpp]: Sum: 5 + +Language: unknown +[INFO] [rclcpp]: Incoming requesta: 2 b: 3[INFO] [rclcpp]: sending back response: [5] diff --git "a/exported_docs/ros2/Writing_a_simple_service_and_client_(Python)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_simple_service_and_client_(Python)\357\203\201.txt" new file mode 100644 index 0000000..a6b9e54 --- /dev/null +++ "b/exported_docs/ros2/Writing_a_simple_service_and_client_(Python)\357\203\201.txt" @@ -0,0 +1,95 @@ +Title: Writing a simple service and client (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Service-And-Client.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a simple service and client (Python)Goal:Create and run service and client nodes using Python.Tutorial level:BeginnerTime:20 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the service node3 Write the client node4 Build and runSummaryNext stepsRelated contentBackgroundWhennodescommunicate usingservices, the node that sends a request for data is called the client node, and the one that responds to the request is the service node. +The structure of the request and response is determined by a.srvfile.The example used here is a simple integer addition system; one node requests the sum of two integers, and the other responds with the result.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Create a packageOpen a new terminal andsource your ROS 2 installationso thatros2commands will work.Navigate into theros2_wsdirectory created in aprevious tutorial.Recall that packages should be created in thesrcdirectory, not the root of the workspace. +Navigate intoros2_ws/srcand create a new package:ros2 pkg create --build-type ament_python --license Apache-2.0 py_srvcli --dependencies rclpy example_interfacesYour terminal will return a message verifying the creation of your packagepy_srvcliand all its necessary files and folders.The--dependenciesargument will automatically add the necessary dependency lines topackage.xml.example_interfacesis the package that includesthe .srv fileyou will need to structure your requests and responses:int64 aint64 b---int64 sumThe first two lines are the parameters of the request, and below the dashes is the response.1.1 Updatepackage.xmlBecause you used the--dependenciesoption during package creation, you don’t have to manually add dependencies topackage.xml.As always, though, make sure to add the description, maintainer email and name, and license information topackage.xml.PythonclientservertutorialYourNameApache-2.01.2 Updatesetup.pyAdd the same information to thesetup.pyfile for themaintainer,maintainer_email,descriptionandlicensefields:maintainer='Your Name',maintainer_email='you@email.com',description='Python client server tutorial',license='Apache-2.0',2 Write the service nodeInside theros2_ws/src/py_srvcli/py_srvclidirectory, create a new file calledservice_member_function.pyand paste the following code within:fromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeclassMinimalService(Node):def__init__(self):super().__init__('minimal_service')self.srv=self.create_service(AddTwoInts,'add_two_ints',self.add_two_ints_callback)defadd_two_ints_callback(self,request,response):response.sum=request.a+request.bself.get_logger().info('Incoming request\na:%db:%d'%(request.a,request.b))returnresponsedefmain():rclpy.init()minimal_service=MinimalService()rclpy.spin(minimal_service)rclpy.shutdown()if__name__=='__main__':main()2.1 Examine the codeThe firstimportstatement imports theAddTwoIntsservice type from theexample_interfacespackage. +The followingimportstatement imports the ROS 2 Python client library, and specifically theNodeclass.fromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeTheMinimalServiceclass constructor initializes the node with the nameminimal_service. +Then, it creates a service and defines the type, name, and callback.def__init__(self):super().__init__('minimal_service')self.srv=self.create_service(AddTwoInts,'add_two_ints',self.add_two_ints_callback)The definition of the service callback receives the request data, sums it, and returns the sum as a response.defadd_two_ints_callback(self,request,response):response.sum=request.a+request.bself.get_logger().info('Incoming request\na:%db:%d'%(request.a,request.b))returnresponseFinally, the main class initializes the ROS 2 Python client library, instantiates theMinimalServiceclass to create the service node and spins the node to handle callbacks.2.2 Add an entry pointTo allow theros2runcommand to run your node, you must add the entry point tosetup.py(located in theros2_ws/src/py_srvclidirectory).Add the following line between the'console_scripts':brackets:'service = py_srvcli.service_member_function:main',3 Write the client nodeInside theros2_ws/src/py_srvcli/py_srvclidirectory, create a new file calledclient_member_function.pyand paste the following code within:importsysfromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeclassMinimalClientAsync(Node):def__init__(self):super().__init__('minimal_client_async')self.cli=self.create_client(AddTwoInts,'add_two_ints')whilenotself.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req=AddTwoInts.Request()defsend_request(self,a,b):self.req.a=aself.req.b=breturnself.cli.call_async(self.req)defmain():rclpy.init()minimal_client=MinimalClientAsync()future=minimal_client.send_request(int(sys.argv[1]),int(sys.argv[2]))rclpy.spin_until_future_complete(minimal_client,future)response=future.result()minimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(int(sys.argv[1]),int(sys.argv[2]),response.sum))minimal_client.destroy_node()rclpy.shutdown()if__name__=='__main__':main()3.1 Examine the codeAs with the service code, we firstimportthe necessary libraries.importsysfromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeTheMinimalClientAsyncclass constructor initializes the node with the nameminimal_client_async. +The constructor definition creates a client with the same type and name as the service node. +The type and name must match for the client and service to be able to communicate. +Thewhileloop in the constructor checks if a service matching the type and name of the client is available once a second. +Finally it creates a newAddTwoIntsrequest object.def__init__(self):super().__init__('minimal_client_async')self.cli=self.create_client(AddTwoInts,'add_two_ints')whilenotself.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req=AddTwoInts.Request()Below the constructor is thesend_requestmethod, which will send the request and spin until it receives the response or fails.defsend_request(self,a,b):self.req.a=aself.req.b=breturnself.cli.call_async(self.req)Finally we have themainmethod, which constructs aMinimalClientAsyncobject, sends the request using the passed-in command-line arguments, callsrclpy.spin_until_future_completeto wait for the result, and logs the results.defmain():rclpy.init()minimal_client=MinimalClientAsync()future=minimal_client.send_request(int(sys.argv[1]),int(sys.argv[2]))rclpy.spin_until_future_complete(minimal_client,future)response=future.result()minimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(int(sys.argv[1]),int(sys.argv[2]),response.sum))minimal_client.destroy_node()rclpy.shutdown()WarningDo not userclpy.spin_until_future_completein a ROS 2 callback. +For more details see thesync deadlock article.3.2 Add an entry pointLike the service node, you also have to add an entry point to be able to run the client node.Theentry_pointsfield of yoursetup.pyfile should look like this:entry_points={'console_scripts':['service = py_srvcli.service_member_function:main','client = py_srvcli.client_member_function:main',],},4 Build and runIt’s good practice to runrosdepin the root of your workspace (ros2_ws) to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you can skip ahead to next step.rosdep only runs on Linux, so you can skip ahead to next step.Navigate back to the root of your workspace,ros2_ws, and build your new package:colcon build --packages-select py_srvcliOpen a new terminal, navigate toros2_ws, and source the setup files:LinuxmacOSWindowssource install/setup.bash. install/setup.bashcall install/setup.batNow run the service node:ros2 run py_srvcli serviceThe node will wait for the client’s request.Open another terminal and source the setup files from insideros2_wsagain. +Start the client node, followed by any two integers separated by a space:ros2 run py_srvcli client 2 3If you chose2and3, for example, the client would receive a response like this:[INFO] [minimal_client_async]: Result of add_two_ints: for 2 + 3 = 5Return to the terminal where your service node is running. +You will see that it published log messages when it received the request:[INFO] [minimal_service]: Incoming requesta: 2 b: 3EnterCtrl+Cin the server terminal to stop the node from spinning.SummaryYou created two nodes to request and respond to data over a service. +You added their dependencies and executables to the package configuration files so that you could build and run them, allowing you to see a service/client system at work.Next stepsIn the last few tutorials you’ve been utilizing interfaces to pass data across topics and services. +Next, you’ll learn how tocreate custom interfaces.Related contentThere are several ways you could write a service and client in Python; check out theminimal_clientandminimal_servicepackages in theros2/examplesrepo.In this tutorial, you used thecall_async()API in your client node to call the service. +There is another service call API available for Python called synchronous calls. +We do not recommend using synchronous calls, but if you’d like to learn more about them, read the guide toSynchronous vs. asynchronous clients. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 py_srvcli --dependencies rclpy example_interfaces + +Language: unknown +int64 aint64 b---int64 sum + +Language: unknown +PythonclientservertutorialYourNameApache-2.0 + +Language: unknown +maintainer='Your Name',maintainer_email='you@email.com',description='Python client server tutorial',license='Apache-2.0', + +Language: unknown +fromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeclassMinimalService(Node):def__init__(self):super().__init__('minimal_service')self.srv=self.create_service(AddTwoInts,'add_two_ints',self.add_two_ints_callback)defadd_two_ints_callback(self,request,response):response.sum=request.a+request.bself.get_logger().info('Incoming request\na:%db:%d'%(request.a,request.b))returnresponsedefmain():rclpy.init()minimal_service=MinimalService()rclpy.spin(minimal_service)rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +fromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNode + +Language: unknown +def__init__(self):super().__init__('minimal_service')self.srv=self.create_service(AddTwoInts,'add_two_ints',self.add_two_ints_callback) + +Language: unknown +defadd_two_ints_callback(self,request,response):response.sum=request.a+request.bself.get_logger().info('Incoming request\na:%db:%d'%(request.a,request.b))returnresponse + +Language: unknown +'service = py_srvcli.service_member_function:main', + +Language: unknown +importsysfromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNodeclassMinimalClientAsync(Node):def__init__(self):super().__init__('minimal_client_async')self.cli=self.create_client(AddTwoInts,'add_two_ints')whilenotself.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req=AddTwoInts.Request()defsend_request(self,a,b):self.req.a=aself.req.b=breturnself.cli.call_async(self.req)defmain():rclpy.init()minimal_client=MinimalClientAsync()future=minimal_client.send_request(int(sys.argv[1]),int(sys.argv[2]))rclpy.spin_until_future_complete(minimal_client,future)response=future.result()minimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(int(sys.argv[1]),int(sys.argv[2]),response.sum))minimal_client.destroy_node()rclpy.shutdown()if__name__=='__main__':main() + +Language: unknown +importsysfromexample_interfaces.srvimportAddTwoIntsimportrclpyfromrclpy.nodeimportNode + +Language: unknown +def__init__(self):super().__init__('minimal_client_async')self.cli=self.create_client(AddTwoInts,'add_two_ints')whilenotself.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req=AddTwoInts.Request() + +Language: unknown +defsend_request(self,a,b):self.req.a=aself.req.b=breturnself.cli.call_async(self.req) + +Language: unknown +defmain():rclpy.init()minimal_client=MinimalClientAsync()future=minimal_client.send_request(int(sys.argv[1]),int(sys.argv[2]))rclpy.spin_until_future_complete(minimal_client,future)response=future.result()minimal_client.get_logger().info('Result of add_two_ints: for%d+%d=%d'%(int(sys.argv[1]),int(sys.argv[2]),response.sum))minimal_client.destroy_node()rclpy.shutdown() + +Language: unknown +entry_points={'console_scripts':['service = py_srvcli.service_member_function:main','client = py_srvcli.client_member_function:main',],}, + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select py_srvcli + +Language: unknown +source install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +call install/setup.bat + +Language: unknown +ros2 run py_srvcli service + +Language: unknown +ros2 run py_srvcli client 2 3 + +Language: unknown +[INFO] [minimal_client_async]: Result of add_two_ints: for 2 + 3 = 5 + +Language: unknown +[INFO] [minimal_service]: Incoming requesta: 2 b: 3 diff --git "a/exported_docs/ros2/Writing_a_static_broadcaster_(C++)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_static_broadcaster_(C++)\357\203\201.txt" new file mode 100644 index 0000000..21fdf34 --- /dev/null +++ "b/exported_docs/ros2/Writing_a_static_broadcaster_(C++)\357\203\201.txt" @@ -0,0 +1,112 @@ +Title: Writing a static broadcaster (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Cpp.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a static broadcaster (C++)Goal:Learn how to broadcast static coordinate frames to tf2.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the static broadcaster node3 Build4 RunThe proper way to publish static transformsSummaryBackgroundPublishing static transforms is useful to define the relationship between a robot base and its sensors or non-moving parts. +For example, it is easiest to reason about laser scan measurements in a frame at the center of the laser scanner.This is a standalone tutorial covering the basics of static transforms, which consists of two parts. +In the first part we will write code to publish static transforms to tf2. +In the second part we will explain how to use the commandlinestatic_transform_publisherexecutable tool intf2_ros.In the next two tutorials we will write the code to reproduce the demo from theIntroduction to tf2tutorial. +After that, the following tutorials focus on extending the demo with more advanced tf2 features.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Create a packageFirst we will create a package that will be used for this tutorial and the following ones. +The package calledlearning_tf2_cppwill depend ongeometry_msgs,rclcpp,tf2,tf2_ros, andturtlesim. +Code for this tutorial is storedhere.Open a new terminal andsource your ROS 2 installationso thatros2commands will work. +Navigate to workspace’ssrcfolder and create a new package:ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies geometry_msgs rclcpp tf2 tf2_ros turtlesim -- learning_tf2_cppYour terminal will return a message verifying the creation of your packagelearning_tf2_cppand all its necessary files and folders.2 Write the static broadcaster nodeLet’s first create the source files. +Inside thesrc/learning_tf2_cpp/srcdirectory download the example static broadcaster code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cppwget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cppIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp -o static_turtle_tf2_broadcaster.cppOr in powershell:curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp -o static_turtle_tf2_broadcaster.cppOpen the file using your preferred text editor.#include#include"geometry_msgs/msg/transform_stamped.hpp"#include"rclcpp/rclcpp.hpp"#include"tf2/LinearMath/Quaternion.h"#include"tf2_ros/static_transform_broadcaster.h"classStaticFramePublisher:publicrclcpp::Node{public:explicitStaticFramePublisher(char*transformation[]):Node("static_turtle_tf2_broadcaster"){tf_static_broadcaster_=std::make_shared(this);// Publish static transforms once at startupthis->make_transforms(transformation);}private:voidmake_transforms(char*transformation[]){geometry_msgs::msg::TransformStampedt;t.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=transformation[1];t.transform.translation.x=atof(transformation[2]);t.transform.translation.y=atof(transformation[3]);t.transform.translation.z=atof(transformation[4]);tf2::Quaternionq;q.setRPY(atof(transformation[5]),atof(transformation[6]),atof(transformation[7]));t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w();tf_static_broadcaster_->sendTransform(t);}std::shared_ptrtf_static_broadcaster_;};intmain(intargc,char*argv[]){autologger=rclcpp::get_logger("logger");// Obtain parameters from command line argumentsif(argc!=8){RCLCPP_INFO(logger,"Invalid number of parameters\nusage: ""$ ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster ""child_frame_name x y z roll pitch yaw");return1;}// As the parent frame of the transform is `world`, it is// necessary to check that the frame name passed is differentif(strcmp(argv[1],"world")==0){RCLCPP_INFO(logger,"Your static turtle name cannot be 'world'");return1;}// Pass parameters and initialize noderclcpp::init(argc,argv);rclcpp::spin(std::make_shared(argv));rclcpp::shutdown();return0;}2.1 Examine the codeNow let’s look at the code that is relevant to publishing the static turtle pose to tf2. +The first lines include the required header files. +First we includegeometry_msgs/msg/transform_stamped.hppto access theTransformStampedmessage type, which we will publish to the transformation tree.#include"geometry_msgs/msg/transform_stamped.hpp"Afterward,rclcppis included so itsrclcpp::Nodeclass can be used.#include"rclcpp/rclcpp.hpp"tf2::Quaternionis a class for a quaternion that provides convenient functions for converting Euler angles to quaternions and vice versa. +We also includetf2_ros/static_transform_broadcaster.hto use theStaticTransformBroadcasterto make the publishing of static transforms easy.#include"tf2/LinearMath/Quaternion.h"#include"tf2_ros/static_transform_broadcaster.h"TheStaticFramePublisherclass constructor initializes the node with the namestatic_turtle_tf2_broadcaster. +Then,StaticTransformBroadcasteris created, which will send one static transformation upon the startup.tf_static_broadcaster_=std::make_shared(this);this->make_transforms(transformation);Here we create aTransformStampedobject, which will be the message we will send over once populated. +Before passing the actual transform values we need to give it the appropriate metadata.We need to give the transform being published a timestamp and we’ll just stamp it with the current time,this->get_clock()->now()Then we need to set the name of the parent frame of the link we’re creating, in this caseworldFinally, we need to set the name of the child frame of the link we’re creatinggeometry_msgs::msg::TransformStampedt;t.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=transformation[1];Here we populate the 6D pose (translation and rotation) of the turtle.t.transform.translation.x=atof(transformation[2]);t.transform.translation.y=atof(transformation[3]);t.transform.translation.z=atof(transformation[4]);tf2::Quaternionq;q.setRPY(atof(transformation[5]),atof(transformation[6]),atof(transformation[7]));t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w();Finally, we broadcast static transform using thesendTransform()function.tf_static_broadcaster_->sendTransform(t);2.2 Update package.xmlNavigate one level back to thesrc/learning_tf2_cppdirectory, where theCMakeLists.txtandpackage.xmlfiles have been created for you.Openpackage.xmlwith your text editor.As mentioned in theCreate a packagetutorial, make sure to fill in the,andtags:Learningtf2withrclcppYourNameApache-2.0Make sure to save the file.2.3 CMakeLists.txtAdd the executable to the CMakeLists.txt and name itstatic_turtle_tf2_broadcaster, which you’ll use later withros2run.add_executable(static_turtle_tf2_broadcaster src/static_turtle_tf2_broadcaster.cpp)ament_target_dependencies(static_turtle_tf2_broadcastergeometry_msgsrclcpptf2tf2_ros)Finally, add theinstall(TARGETS…)section soros2runcan find your executable:install(TARGETSstatic_turtle_tf2_broadcasterDESTINATION lib/${PROJECT_NAME})3 BuildIt’s good practice to runrosdepin the root of your workspace to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfStill in the root of your workspace, build your new package:LinuxmacOSWindowscolcon build --packages-select learning_tf2_cppcolcon build --packages-select learning_tf2_cppcolcon build --merge-install --packages-select learning_tf2_cppOpen a new terminal, navigate to the root of your workspace, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bash#CMDcall install\setup.bat#Powershell.\install\setup.ps14 RunNow run thestatic_turtle_tf2_broadcasternode:ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0This sets a turtle pose broadcast formystaticturtleto float 1 meter above the ground.We can now check that the static transform has been published by echoing thetf_statictopicros2 topic echo /tf_staticIf everything went well you should see a single static transformtransforms:- header:stamp:sec: 1622908754nanosec: 208515730frame_id: worldchild_frame_id: mystaticturtletransform:translation:x: 0.0y: 0.0z: 1.0rotation:x: 0.0y: 0.0z: 0.0w: 1.0The proper way to publish static transformsThis tutorial aimed to show howStaticTransformBroadcastercan be used to publish static transforms. +In your real development process you shouldn’t have to write this code yourself and should use the dedicatedtf2_rostool to do so.tf2_rosprovides an executable namedstatic_transform_publisherthat can be used either as a commandline tool or a node that you can add to your launchfiles.The following command publishes a static coordinate transform to tf2 using an x/y/z offset in meters and roll/pitch/yaw in radians. +In ROS 2, roll/pitch/yaw refers to rotation about the x/y/z-axis, respectively.ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_idThe following command publishes a static coordinate transform to tf2 using an x/y/z offset in meters and roll/pitch/yaw as a quaternion.ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_idstatic_transform_publisheris designed both as a command-line tool for manual use, as well as for use withinlaunchfiles for setting static transforms. For example:from launch import LaunchDescriptionfrom launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='tf2_ros',executable='static_transform_publisher',arguments = ['--x', '0', '--y', '0', '--z', '1', '--yaw', '0', '--pitch', '0', '--roll', '0', '--frame-id', 'world', '--child-frame-id', 'mystaticturtle']),])Note that all arguments except for--frame-idand--child-frame-idare optional; if a particular option isn’t specified, then the identity will be assumed.SummaryIn this tutorial you learned how static transforms are useful to define static relationships between frames, likemystaticturtlein relation to theworldframe. +In addition, you learned how static transforms can be useful for understanding sensor data, such as from laser scanners, by relating the data to a common coordinate frame. +Finally, you wrote your own node to publish static transforms to tf2 and learned how to publish required static transformations usingstatic_transform_publisherexecutable and launch files. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies geometry_msgs rclcpp tf2 tf2_ros turtlesim -- learning_tf2_cpp + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp -o static_turtle_tf2_broadcaster.cpp + +Language: unknown +curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_cpp/src/static_turtle_tf2_broadcaster.cpp -o static_turtle_tf2_broadcaster.cpp + +Language: unknown +#include#include"geometry_msgs/msg/transform_stamped.hpp"#include"rclcpp/rclcpp.hpp"#include"tf2/LinearMath/Quaternion.h"#include"tf2_ros/static_transform_broadcaster.h"classStaticFramePublisher:publicrclcpp::Node{public:explicitStaticFramePublisher(char*transformation[]):Node("static_turtle_tf2_broadcaster"){tf_static_broadcaster_=std::make_shared(this);// Publish static transforms once at startupthis->make_transforms(transformation);}private:voidmake_transforms(char*transformation[]){geometry_msgs::msg::TransformStampedt;t.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=transformation[1];t.transform.translation.x=atof(transformation[2]);t.transform.translation.y=atof(transformation[3]);t.transform.translation.z=atof(transformation[4]);tf2::Quaternionq;q.setRPY(atof(transformation[5]),atof(transformation[6]),atof(transformation[7]));t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w();tf_static_broadcaster_->sendTransform(t);}std::shared_ptrtf_static_broadcaster_;};intmain(intargc,char*argv[]){autologger=rclcpp::get_logger("logger");// Obtain parameters from command line argumentsif(argc!=8){RCLCPP_INFO(logger,"Invalid number of parameters\nusage: ""$ ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster ""child_frame_name x y z roll pitch yaw");return1;}// As the parent frame of the transform is `world`, it is// necessary to check that the frame name passed is differentif(strcmp(argv[1],"world")==0){RCLCPP_INFO(logger,"Your static turtle name cannot be 'world'");return1;}// Pass parameters and initialize noderclcpp::init(argc,argv);rclcpp::spin(std::make_shared(argv));rclcpp::shutdown();return0;} + +Language: unknown +#include"geometry_msgs/msg/transform_stamped.hpp" + +Language: unknown +#include"rclcpp/rclcpp.hpp" + +Language: unknown +#include"tf2/LinearMath/Quaternion.h"#include"tf2_ros/static_transform_broadcaster.h" + +Language: unknown +tf_static_broadcaster_=std::make_shared(this);this->make_transforms(transformation); + +Language: unknown +geometry_msgs::msg::TransformStampedt;t.header.stamp=this->get_clock()->now();t.header.frame_id="world";t.child_frame_id=transformation[1]; + +Language: unknown +t.transform.translation.x=atof(transformation[2]);t.transform.translation.y=atof(transformation[3]);t.transform.translation.z=atof(transformation[4]);tf2::Quaternionq;q.setRPY(atof(transformation[5]),atof(transformation[6]),atof(transformation[7]));t.transform.rotation.x=q.x();t.transform.rotation.y=q.y();t.transform.rotation.z=q.z();t.transform.rotation.w=q.w(); + +Language: unknown +tf_static_broadcaster_->sendTransform(t); + +Language: unknown +Learningtf2withrclcppYourNameApache-2.0 + +Language: unknown +add_executable(static_turtle_tf2_broadcaster src/static_turtle_tf2_broadcaster.cpp)ament_target_dependencies(static_turtle_tf2_broadcastergeometry_msgsrclcpptf2tf2_ros) + +Language: unknown +install(TARGETSstatic_turtle_tf2_broadcasterDESTINATION lib/${PROJECT_NAME}) + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select learning_tf2_cpp + +Language: unknown +colcon build --packages-select learning_tf2_cpp + +Language: unknown +colcon build --merge-install --packages-select learning_tf2_cpp + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +#CMDcall install\setup.bat#Powershell.\install\setup.ps1 + +Language: unknown +ros2 run learning_tf2_cpp static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0 + +Language: unknown +ros2 topic echo /tf_static + +Language: unknown +transforms:- header:stamp:sec: 1622908754nanosec: 208515730frame_id: worldchild_frame_id: mystaticturtletransform:translation:x: 0.0y: 0.0z: 1.0rotation:x: 0.0y: 0.0z: 0.0w: 1.0 + +Language: unknown +ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_id + +Language: unknown +ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_id + +Language: unknown +from launch import LaunchDescriptionfrom launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='tf2_ros',executable='static_transform_publisher',arguments = ['--x', '0', '--y', '0', '--z', '1', '--yaw', '0', '--pitch', '0', '--roll', '0', '--frame-id', 'world', '--child-frame-id', 'mystaticturtle']),]) diff --git "a/exported_docs/ros2/Writing_a_static_broadcaster_(Python)\357\203\201.txt" "b/exported_docs/ros2/Writing_a_static_broadcaster_(Python)\357\203\201.txt" new file mode 100644 index 0000000..ccd25af --- /dev/null +++ "b/exported_docs/ros2/Writing_a_static_broadcaster_(Python)\357\203\201.txt" @@ -0,0 +1,112 @@ +Title: Writing a static broadcaster (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Py.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing a static broadcaster (Python)Goal:Learn how to broadcast static coordinate frames to tf2.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Create a package2 Write the static broadcaster node3 Build4 RunThe proper way to publish static transformsSummaryBackgroundPublishing static transforms is useful to define the relationship between a robot base and its sensors or non-moving parts. +For example, it is easiest to reason about laser scan measurements in a frame at the center of the laser scanner.This is a standalone tutorial covering the basics of static transforms, which consists of two parts. +In the first part we will write code to publish static transforms to tf2. +In the second part we will explain how to use the commandlinestatic_transform_publisherexecutable tool intf2_ros.In the next two tutorials we will write the code to reproduce the demo from theIntroduction to tf2tutorial. +After that, the following tutorials focus on extending the demo with more advanced tf2 features.PrerequisitesIn previous tutorials, you learned how tocreate a workspaceandcreate a package.Tasks1 Create a packageFirst we will create a package that will be used for this tutorial and the following ones. +The package calledlearning_tf2_pywill depend ongeometry_msgs,python3-numpy,rclpy,tf2_ros_py, andturtlesim. +Code for this tutorial is storedhere.Open a new terminal andsource your ROS 2 installationso thatros2commands will work. +Navigate to workspace’ssrcfolder and create a new package:ros2 pkg create --build-type ament_python --license Apache-2.0 -- learning_tf2_pyYour terminal will return a message verifying the creation of your packagelearning_tf2_pyand all its necessary files and folders.2 Write the static broadcaster nodeLet’s first create the source files. +Inside thesrc/learning_tf2_py/learning_tf2_pydirectory download the example static broadcaster code by entering the following command:LinuxmacOSWindowswget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.pywget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.pyIn a Windows command line prompt:curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.py -o static_turtle_tf2_broadcaster.pyOr in powershell:curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.py -o static_turtle_tf2_broadcaster.pyNow open the file calledstatic_turtle_tf2_broadcaster.pyusing your preferred text editor.importmathimportsysfromgeometry_msgs.msgimportTransformStampedimportnumpyasnpimportrclpyfromrclpy.nodeimportNodefromtf2_ros.static_transform_broadcasterimportStaticTransformBroadcasterdefquaternion_from_euler(ai,aj,ak):ai/=2.0aj/=2.0ak/=2.0ci=math.cos(ai)si=math.sin(ai)cj=math.cos(aj)sj=math.sin(aj)ck=math.cos(ak)sk=math.sin(ak)cc=ci*ckcs=ci*sksc=si*ckss=si*skq=np.empty((4,))q[0]=cj*sc-sj*csq[1]=cj*ss+sj*ccq[2]=cj*cs-sj*scq[3]=cj*cc+sj*ssreturnqclassStaticFramePublisher(Node):"""Broadcast transforms that never change.This example publishes transforms from `world` to a static turtle frame.The transforms are only published once at startup, and are constant for alltime."""def__init__(self,transformation):super().__init__('static_turtle_tf2_broadcaster')self.tf_static_broadcaster=StaticTransformBroadcaster(self)# Publish static transforms once at startupself.make_transforms(transformation)defmake_transforms(self,transformation):t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='world't.child_frame_id=transformation[1]t.transform.translation.x=float(transformation[2])t.transform.translation.y=float(transformation[3])t.transform.translation.z=float(transformation[4])quat=quaternion_from_euler(float(transformation[5]),float(transformation[6]),float(transformation[7]))t.transform.rotation.x=quat[0]t.transform.rotation.y=quat[1]t.transform.rotation.z=quat[2]t.transform.rotation.w=quat[3]self.tf_static_broadcaster.sendTransform(t)defmain():logger=rclpy.logging.get_logger('logger')# obtain parameters from command line argumentsiflen(sys.argv)!=8:logger.info('Invalid number of parameters. Usage:\n''$ ros2 run learning_tf2_py static_turtle_tf2_broadcaster''child_frame_name x y z roll pitch yaw')sys.exit(1)ifsys.argv[1]=='world':logger.info('Your static turtle name cannot be "world"')sys.exit(2)# pass parameters and initialize noderclpy.init()node=StaticFramePublisher(sys.argv)try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown()2.1 Examine the codeNow let’s look at the code that is relevant to publishing the static turtle pose to tf2. +The first lines import required packages. +First we import theTransformStampedfrom thegeometry_msgs, which provides us a template for the message that we will publish to the transformation tree.fromgeometry_msgs.msgimportTransformStampedAfterward,rclpyis imported so itsNodeclass can be used.importrclpyfromrclpy.nodeimportNodeThetf2_rospackage provides aStaticTransformBroadcasterto make the publishing of static transforms easy. +To use theStaticTransformBroadcaster, we need to import it from thetf2_rosmodule.fromtf2_ros.static_transform_broadcasterimportStaticTransformBroadcasterTheStaticFramePublisherclass constructor initializes the node with the namestatic_turtle_tf2_broadcaster. +Then,StaticTransformBroadcasteris created, which will send one static transformation upon the startup.self.tf_static_broadcaster=StaticTransformBroadcaster(self)self.make_transforms(transformation)Here we create aTransformStampedobject, which will be the message we will send over once populated. +Before passing the actual transform values we need to give it the appropriate metadata.We need to give the transform being published a timestamp and we’ll just stamp it with the current time,self.get_clock().now()Then we need to set the name of the parent frame of the link we’re creating, in this caseworldFinally, we need to set the name of the child frame of the link we’re creatingt=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='world't.child_frame_id=transformation[1]Here we populate the 6D pose (translation and rotation) of the turtle.t.transform.translation.x=float(transformation[2])t.transform.translation.y=float(transformation[3])t.transform.translation.z=float(transformation[4])quat=quaternion_from_euler(float(transformation[5]),float(transformation[6]),float(transformation[7]))t.transform.rotation.x=quat[0]t.transform.rotation.y=quat[1]t.transform.rotation.z=quat[2]t.transform.rotation.w=quat[3]Finally, we broadcast static transform using thesendTransform()function.self.tf_static_broadcaster.sendTransform(t)2.2 Update package.xmlNavigate one level back to thesrc/learning_tf2_pydirectory, where thesetup.py,setup.cfg, andpackage.xmlfiles have been created for you.Openpackage.xmlwith your text editor.As mentioned in theCreate a packagetutorial, make sure to fill in the,andtags:Learningtf2withrclpyYourNameApache-2.0After the lines above, add the following dependencies corresponding to your node’s import statements:geometry_msgspython3-numpyrclpytf2_ros_pyturtlesimThis declares the requiredgeometry_msgs,python3-numpy,rclpy,tf2_ros_py, andturtlesimdependencies when its code is executed.Make sure to save the file.2.3 Add an entry pointTo allow theros2runcommand to run your node, you must add the entry point tosetup.py(located in thesrc/learning_tf2_pydirectory).Add the following line between the'console_scripts':brackets:'static_turtle_tf2_broadcaster = learning_tf2_py.static_turtle_tf2_broadcaster:main',3 BuildIt’s good practice to runrosdepin the root of your workspace to check for missing dependencies before building:LinuxmacOSWindowsrosdep install -i --from-path src --rosdistro jazzy -yrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfrosdep only runs on Linux, so you will need to installgeometry_msgsandturtlesimdependencies yourselfStill in the root of your workspace, build your new package:LinuxmacOSWindowscolcon build --packages-select learning_tf2_pycolcon build --packages-select learning_tf2_pycolcon build --merge-install --packages-select learning_tf2_pyOpen a new terminal, navigate to the root of your workspace, and source the setup files:LinuxmacOSWindows. install/setup.bash. install/setup.bash#CMDcall install\setup.bat#Powershell.\install\setup.ps14 RunNow run thestatic_turtle_tf2_broadcasternode:ros2 run learning_tf2_py static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0This sets a turtle pose broadcast formystaticturtleto float 1 meter above the ground.We can now check that the static transform has been published by echoing thetf_statictopicros2 topic echo /tf_staticIf everything went well you should see a single static transformtransforms:- header:stamp:sec: 1622908754nanosec: 208515730frame_id: worldchild_frame_id: mystaticturtletransform:translation:x: 0.0y: 0.0z: 1.0rotation:x: 0.0y: 0.0z: 0.0w: 1.0The proper way to publish static transformsThis tutorial aimed to show howStaticTransformBroadcastercan be used to publish static transforms. +In your real development process you shouldn’t have to write this code yourself and should use the dedicatedtf2_rostool to do so.tf2_rosprovides an executable namedstatic_transform_publisherthat can be used either as a commandline tool or a node that you can add to your launchfiles.The following command publishes a static coordinate transform to tf2 using an x/y/z offset in meters and roll/pitch/yaw in radians. +In ROS 2, roll/pitch/yaw refers to rotation about the x/y/z-axis, respectively.ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_idThe following command publishes a static coordinate transform to tf2 using an x/y/z offset in meters and roll/pitch/yaw as a quaternion.ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_idstatic_transform_publisheris designed both as a command-line tool for manual use, as well as for use withinlaunchfiles for setting static transforms. For example:fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='tf2_ros',executable='static_transform_publisher',arguments=['--x','0','--y','0','--z','1','--yaw','0','--pitch','0','--roll','0','--frame-id','world','--child-frame-id','mystaticturtle']),])Note that all arguments except for--frame-idand--child-frame-idare optional; if a particular option isn’t specified, then the identity will be assumed.SummaryIn this tutorial you learned how static transforms are useful to define static relationships between frames, likemystaticturtlein relation to theworldframe. +In addition, you learned how static transforms can be useful for understanding sensor data, such as from laser scanners, by relating the data to a common coordinate frame. +Finally, you wrote your own node to publish static transforms to tf2 and learned how to publish required static transformations usingstatic_transform_publisherexecutable and launch files. + +Code Examples: + +Language: unknown +ros2 pkg create --build-type ament_python --license Apache-2.0 -- learning_tf2_py + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.py + +Language: unknown +wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.py + +Language: unknown +curl -sk https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.py -o static_turtle_tf2_broadcaster.py + +Language: unknown +curl https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/static_turtle_tf2_broadcaster.py -o static_turtle_tf2_broadcaster.py + +Language: unknown +importmathimportsysfromgeometry_msgs.msgimportTransformStampedimportnumpyasnpimportrclpyfromrclpy.nodeimportNodefromtf2_ros.static_transform_broadcasterimportStaticTransformBroadcasterdefquaternion_from_euler(ai,aj,ak):ai/=2.0aj/=2.0ak/=2.0ci=math.cos(ai)si=math.sin(ai)cj=math.cos(aj)sj=math.sin(aj)ck=math.cos(ak)sk=math.sin(ak)cc=ci*ckcs=ci*sksc=si*ckss=si*skq=np.empty((4,))q[0]=cj*sc-sj*csq[1]=cj*ss+sj*ccq[2]=cj*cs-sj*scq[3]=cj*cc+sj*ssreturnqclassStaticFramePublisher(Node):"""Broadcast transforms that never change.This example publishes transforms from `world` to a static turtle frame.The transforms are only published once at startup, and are constant for alltime."""def__init__(self,transformation):super().__init__('static_turtle_tf2_broadcaster')self.tf_static_broadcaster=StaticTransformBroadcaster(self)# Publish static transforms once at startupself.make_transforms(transformation)defmake_transforms(self,transformation):t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='world't.child_frame_id=transformation[1]t.transform.translation.x=float(transformation[2])t.transform.translation.y=float(transformation[3])t.transform.translation.z=float(transformation[4])quat=quaternion_from_euler(float(transformation[5]),float(transformation[6]),float(transformation[7]))t.transform.rotation.x=quat[0]t.transform.rotation.y=quat[1]t.transform.rotation.z=quat[2]t.transform.rotation.w=quat[3]self.tf_static_broadcaster.sendTransform(t)defmain():logger=rclpy.logging.get_logger('logger')# obtain parameters from command line argumentsiflen(sys.argv)!=8:logger.info('Invalid number of parameters. Usage:\n''$ ros2 run learning_tf2_py static_turtle_tf2_broadcaster''child_frame_name x y z roll pitch yaw')sys.exit(1)ifsys.argv[1]=='world':logger.info('Your static turtle name cannot be "world"')sys.exit(2)# pass parameters and initialize noderclpy.init()node=StaticFramePublisher(sys.argv)try:rclpy.spin(node)exceptKeyboardInterrupt:passrclpy.shutdown() + +Language: unknown +fromgeometry_msgs.msgimportTransformStamped + +Language: unknown +importrclpyfromrclpy.nodeimportNode + +Language: unknown +fromtf2_ros.static_transform_broadcasterimportStaticTransformBroadcaster + +Language: unknown +self.tf_static_broadcaster=StaticTransformBroadcaster(self)self.make_transforms(transformation) + +Language: unknown +t=TransformStamped()t.header.stamp=self.get_clock().now().to_msg()t.header.frame_id='world't.child_frame_id=transformation[1] + +Language: unknown +t.transform.translation.x=float(transformation[2])t.transform.translation.y=float(transformation[3])t.transform.translation.z=float(transformation[4])quat=quaternion_from_euler(float(transformation[5]),float(transformation[6]),float(transformation[7]))t.transform.rotation.x=quat[0]t.transform.rotation.y=quat[1]t.transform.rotation.z=quat[2]t.transform.rotation.w=quat[3] + +Language: unknown +self.tf_static_broadcaster.sendTransform(t) + +Language: unknown +Learningtf2withrclpyYourNameApache-2.0 + +Language: unknown +geometry_msgspython3-numpyrclpytf2_ros_pyturtlesim + +Language: unknown +'static_turtle_tf2_broadcaster = learning_tf2_py.static_turtle_tf2_broadcaster:main', + +Language: unknown +rosdep install -i --from-path src --rosdistro jazzy -y + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --packages-select learning_tf2_py + +Language: unknown +colcon build --merge-install --packages-select learning_tf2_py + +Language: unknown +. install/setup.bash + +Language: unknown +. install/setup.bash + +Language: unknown +#CMDcall install\setup.bat#Powershell.\install\setup.ps1 + +Language: unknown +ros2 run learning_tf2_py static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0 + +Language: unknown +ros2 topic echo /tf_static + +Language: unknown +transforms:- header:stamp:sec: 1622908754nanosec: 208515730frame_id: worldchild_frame_id: mystaticturtletransform:translation:x: 0.0y: 0.0z: 1.0rotation:x: 0.0y: 0.0z: 0.0w: 1.0 + +Language: unknown +ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_id + +Language: unknown +ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_id + +Language: unknown +fromlaunchimportLaunchDescriptionfromlaunch_ros.actionsimportNodedefgenerate_launch_description():returnLaunchDescription([Node(package='tf2_ros',executable='static_transform_publisher',arguments=['--x','0','--y','0','--z','1','--yaw','0','--pitch','0','--roll','0','--frame-id','world','--child-frame-id','mystaticturtle']),]) diff --git "a/exported_docs/ros2/Writing_an_action_server_and_client_(C++)\357\203\201.txt" "b/exported_docs/ros2/Writing_an_action_server_and_client_(C++)\357\203\201.txt" new file mode 100644 index 0000000..c5470c8 --- /dev/null +++ "b/exported_docs/ros2/Writing_an_action_server_and_client_(C++)\357\203\201.txt" @@ -0,0 +1,108 @@ +Title: Writing an action server and client (C++) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Writing-an-Action-Server-Client/Cpp.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing an action server and client (C++)Goal:Implement an action server and client in C++.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Creating the custom_action_cpp package2 Writing an action server3 Writing an action clientSummaryRelated contentBackgroundActions are a form of asynchronous communication in ROS.Action clientssend goal requests toaction servers.Action serverssend goal feedback and results toaction clients.PrerequisitesYou will need thecustom_action_interfacespackage and theFibonacci.actioninterface defined in the previous tutorial,Creating an action.Tasks1 Creating the custom_action_cpp packageAs we saw in theCreating a packagetutorial, we need to create a new package to hold our C++ and supporting code.1.1 Creating the custom_action_cpp packageGo into the action workspace you created in theprevious tutorial(remember to source the workspace), and create a new package for the C++ action server:LinuxmacOSWindowscd~/ros2_ws/src +ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cppcd~/ros2_ws/src +ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cppcd\ros2_ws\src +ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cpp1.2 Adding in visibility controlIn order to make the package compile and work on Windows, we need to add in some “visibility control”. +For more details, seeWindows Symbol Visibility in the Windows Tips and Tricks document.Open upcustom_action_cpp/include/custom_action_cpp/visibility_control.h, and put the following code in:#ifndef CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#define CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#ifdef __cplusplusextern"C"{#endif// This logic was borrowed (then namespaced) from the examples on the gcc wiki:// https://gcc.gnu.org/wiki/Visibility#if defined _WIN32 || defined __CYGWIN__#ifdef __GNUC__#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((dllexport))#define CUSTOM_ACTION_CPP_IMPORT __attribute__ ((dllimport))#else#define CUSTOM_ACTION_CPP_EXPORT __declspec(dllexport)#define CUSTOM_ACTION_CPP_IMPORT __declspec(dllimport)#endif#ifdef CUSTOM_ACTION_CPP_BUILDING_DLL#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_EXPORT#else#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_IMPORT#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#else#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_IMPORT#if __GNUC__ >= 4#define CUSTOM_ACTION_CPP_PUBLIC __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_LOCAL __attribute__ ((visibility("hidden")))#else#define CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE#endif#ifdef __cplusplus}#endif#endif// CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_2 Writing an action serverLet’s focus on writing an action server that computes the Fibonacci sequence using the action we created in theCreating an actiontutorial.2.1 Writing the action server codeOpen upcustom_action_cpp/src/fibonacci_action_server.cpp, and put the following code in:#include#include#include#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"custom_action_cpp/visibility_control.h"namespacecustom_action_cpp{classFibonacciActionServer:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ServerGoalHandle;CUSTOM_ACTION_CPP_PUBLICexplicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options){usingnamespacestd::placeholders;autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptrgoal){RCLCPP_INFO(this->get_logger(),"Received goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;};autohandle_cancel=[this](conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;};autohandle_accepted=[this](conststd::shared_ptrgoal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();};this->action_server_=rclcpp_action::create_server(this,"fibonacci",handle_goal,handle_cancel,handle_accepted);}private:rclcpp_action::Server::SharedPtraction_server_;voidexecute(conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Executing goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared();for(inti=1;(iorder)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};};// class FibonacciActionServer}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionServer)The first few lines include all of the headers we need to compile.Next we create a class that is a derived class ofrclcpp::Node:classFibonacciActionServer:publicrclcpp::NodeThe constructor for theFibonacciActionServerclass initializes the node name asfibonacci_action_server:explicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options)The constructor also instantiates a new action server:loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){An action server requires 6 things:The templated action type name:Fibonacci.A ROS 2 node to add the action to:this.The action name:'fibonacci'.A callback function for handling goals:handle_goalA callback function for handling cancellation:handle_cancel.A callback function for handling goal accept:handle_accept.The implementation of the various callbacks is done with [lambda expressions](https://en.cppreference.com/w/cpp/language/lambda) within the constructor. +Note that all of the callbacks need to return quickly, otherwise we risk starving the executor.We start with the callback for handling new goals:autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptrgoal){RCLCPP_INFO(this->get_logger(),"Received goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;};This implementation just accepts all goals.Next up is the callback for dealing with cancellation:autohandle_cancel=[this](conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;};This implementation just tells the client that it accepted the cancellation.The last of the callbacks accepts a new goal and starts processing it:autohandle_accepted=[this](conststd::shared_ptrgoal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();};Since the execution is a long-running operation, we spawn off a thread to do the actual work and return fromhandle_acceptedquickly.All further processing and updates are done in theexecutemethod in the new thread:voidexecute(conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Executing goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared();for(inti=1;(iorder)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};This work thread processes one sequence number of the Fibonacci sequence every second, publishing a feedback update for each step. +When it has finished processing, it marks thegoal_handleas succeeded, and quits.We now have a fully functioning action server. Let’s get it built and running.2.2 Compiling the action serverIn the previous section we put the action server code into place. +To get it to compile and run, we need to do a couple of additional things.First we need to setup the CMakeLists.txt so that the action server is compiled. +Open upcustom_action_cpp/CMakeLists.txt, and add the following right after thefind_packagecalls:add_library(action_serverSHAREDsrc/fibonacci_action_server.cpp)target_include_directories(action_serverPRIVATE$$)target_compile_definitions(action_serverPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_server"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_serverPLUGIN"custom_action_cpp::FibonacciActionServer"EXECUTABLEfibonacci_action_server)install(TARGETSaction_serverARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)And now we can compile the package. Go to the top-level of theros2_ws, and run:colconbuildThis should compile the entire workspace, including thefibonacci_action_serverin thecustom_action_cpppackage.2.3 Running the action serverNow that we have the action server built, we can run it. +Source the workspace we just built (ros2_ws), and try to run the action server:ros2runcustom_action_cppfibonacci_action_server3 Writing an action client3.1 Writing the action client codeOpen upcustom_action_cpp/src/fibonacci_action_client.cpp, and put the following code in:#include#include#include#include#include#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"namespacecustom_action_cpp{classFibonacciActionClient:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ClientGoalHandle;explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options){this->client_ptr_=rclcpp_action::create_client(this,"fibonacci");autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);}voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptrfeedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}private:rclcpp_action::Client::SharedPtrclient_ptr_;rclcpp::TimerBase::SharedPtrtimer_;};// class FibonacciActionClient}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionClient)The first few lines include all of the headers we need to compile.Next we create a class that is a derived class ofrclcpp::Node:classFibonacciActionClient:publicrclcpp::NodeThe constructor for theFibonacciActionClientclass initializes the node name asfibonacci_action_client:explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options)The constructor also instantiates a new action client:this->client_ptr_=rclcpp_action::create_client(this,"fibonacci");An action client requires 3 things:The templated action type name:Fibonacci.A ROS 2 node to add the action client to:this.The action name:'fibonacci'.We also instantiate a ROS timer that will kick off the one and only call tosend_goal:autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);When the timer expires, it will callsend_goal:voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptrfeedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}This function does the following:Cancels the timer (so it is only called once).Waits for the action server to come up.Instantiates a newFibonacci::Goal.Sets the response, feedback, and result callbacks.Sends the goal to the server.When the server receives and accepts the goal, it will send a response to the client. +That response is handled bygoal_response_callback:send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};Assuming the goal was accepted by the server, it will start processing. +Any feedback to the client will be handled by thefeedback_callback:send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptrfeedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<get_logger(),ss.str().c_str());};When the server is finished processing, it will return a result to the client. +The result is handled by theresult_callback:send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<get_logger(),ss.str().c_str());rclcpp::shutdown();};We now have a fully functioning action client. Let’s get it built and running.3.2 Compiling the action clientIn the previous section we put the action client code into place. +To get it to compile and run, we need to do a couple of additional things.First we need to setup the CMakeLists.txt so that the action client is compiled. +Open upcustom_action_cpp/CMakeLists.txt, and add the following right after thefind_packagecalls:add_library(action_clientSHAREDsrc/fibonacci_action_client.cpp)target_include_directories(action_clientPRIVATE$$)target_compile_definitions(action_clientPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_client"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_clientPLUGIN"custom_action_cpp::FibonacciActionClient"EXECUTABLEfibonacci_action_client)install(TARGETSaction_clientARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin)And now we can compile the package. Go to the top-level of theros2_ws, and run:colconbuildThis should compile the entire workspace, including thefibonacci_action_clientin thecustom_action_cpppackage.3.3 Running the action clientNow that we have the action client built, we can run it. +First make sure that an action server is running in a separate terminal. +Now source the workspace we just built (ros2_ws), and try to run the action client:ros2runcustom_action_cppfibonacci_action_clientYou should see logged messages for the goal being accepted, feedback being printed, and the final result.SummaryIn this tutorial, you put together a C++ action server and action client line by line, and configured them to exchange goals, feedback, and results.Related contentThere are several ways you could write an action server and client in C++; check out theminimal_action_serverandminimal_action_clientpackages in theros2/examplesrepo.For more detailed information about ROS actions, please refer to thedesign article. + +Code Examples: + +Language: unknown +cd~/ros2_ws/src +ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cpp + +Language: unknown +cd~/ros2_ws/src +ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cpp + +Language: unknown +cd\ros2_ws\src +ros2pkgcreate--dependenciescustom_action_interfacesrclcpprclcpp_actionrclcpp_components--licenseApache-2.0--custom_action_cpp + +Language: unknown +#ifndef CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#define CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_#ifdef __cplusplusextern"C"{#endif// This logic was borrowed (then namespaced) from the examples on the gcc wiki:// https://gcc.gnu.org/wiki/Visibility#if defined _WIN32 || defined __CYGWIN__#ifdef __GNUC__#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((dllexport))#define CUSTOM_ACTION_CPP_IMPORT __attribute__ ((dllimport))#else#define CUSTOM_ACTION_CPP_EXPORT __declspec(dllexport)#define CUSTOM_ACTION_CPP_IMPORT __declspec(dllimport)#endif#ifdef CUSTOM_ACTION_CPP_BUILDING_DLL#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_EXPORT#else#define CUSTOM_ACTION_CPP_PUBLIC CUSTOM_ACTION_CPP_IMPORT#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#else#define CUSTOM_ACTION_CPP_EXPORT __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_IMPORT#if __GNUC__ >= 4#define CUSTOM_ACTION_CPP_PUBLIC __attribute__ ((visibility("default")))#define CUSTOM_ACTION_CPP_LOCAL __attribute__ ((visibility("hidden")))#else#define CUSTOM_ACTION_CPP_PUBLIC#define CUSTOM_ACTION_CPP_LOCAL#endif#define CUSTOM_ACTION_CPP_PUBLIC_TYPE#endif#ifdef __cplusplus}#endif#endif// CUSTOM_ACTION_CPP__VISIBILITY_CONTROL_H_ + +Language: unknown +#include#include#include#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"custom_action_cpp/visibility_control.h"namespacecustom_action_cpp{classFibonacciActionServer:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ServerGoalHandle;CUSTOM_ACTION_CPP_PUBLICexplicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options){usingnamespacestd::placeholders;autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptrgoal){RCLCPP_INFO(this->get_logger(),"Received goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;};autohandle_cancel=[this](conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;};autohandle_accepted=[this](conststd::shared_ptrgoal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();};this->action_server_=rclcpp_action::create_server(this,"fibonacci",handle_goal,handle_cancel,handle_accepted);}private:rclcpp_action::Server::SharedPtraction_server_;voidexecute(conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Executing goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared();for(inti=1;(iorder)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}};};// class FibonacciActionServer}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionServer) + +Language: unknown +classFibonacciActionServer:publicrclcpp::Node + +Language: unknown +explicitFibonacciActionServer(constrclcpp::NodeOptions&options=rclcpp::NodeOptions()):Node("fibonacci_action_server",options) + +Language: unknown +loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){ + +Language: unknown +autohandle_goal=[this](constrclcpp_action::GoalUUID&uuid,std::shared_ptrgoal){RCLCPP_INFO(this->get_logger(),"Received goal request with order %d",goal->order);(void)uuid;returnrclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;}; + +Language: unknown +autohandle_cancel=[this](conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Received request to cancel goal");(void)goal_handle;returnrclcpp_action::CancelResponse::ACCEPT;}; + +Language: unknown +autohandle_accepted=[this](conststd::shared_ptrgoal_handle){// this needs to return quickly to avoid blocking the executor,// so we declare a lambda function to be called inside a new threadautoexecute_in_thread=[this,goal_handle](){returnthis->execute(goal_handle);};std::thread{execute_in_thread}.detach();}; + +Language: unknown +voidexecute(conststd::shared_ptrgoal_handle){RCLCPP_INFO(this->get_logger(),"Executing goal");rclcpp::Rateloop_rate(1);constautogoal=goal_handle->get_goal();autofeedback=std::make_shared();auto&sequence=feedback->partial_sequence;sequence.push_back(0);sequence.push_back(1);autoresult=std::make_shared();for(inti=1;(iorder)&&rclcpp::ok();++i){// Check if there is a cancel requestif(goal_handle->is_canceling()){result->sequence=sequence;goal_handle->canceled(result);RCLCPP_INFO(this->get_logger(),"Goal canceled");return;}// Update sequencesequence.push_back(sequence[i]+sequence[i-1]);// Publish feedbackgoal_handle->publish_feedback(feedback);RCLCPP_INFO(this->get_logger(),"Publish feedback");loop_rate.sleep();}// Check if goal is doneif(rclcpp::ok()){result->sequence=sequence;goal_handle->succeed(result);RCLCPP_INFO(this->get_logger(),"Goal succeeded");}}; + +Language: unknown +add_library(action_serverSHAREDsrc/fibonacci_action_server.cpp)target_include_directories(action_serverPRIVATE$$)target_compile_definitions(action_serverPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_server"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_serverPLUGIN"custom_action_cpp::FibonacciActionServer"EXECUTABLEfibonacci_action_server)install(TARGETSaction_serverARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin) + +Language: unknown +colconbuild + +Language: unknown +ros2runcustom_action_cppfibonacci_action_server + +Language: unknown +#include#include#include#include#include#include"custom_action_interfaces/action/fibonacci.hpp"#include"rclcpp/rclcpp.hpp"#include"rclcpp_action/rclcpp_action.hpp"#include"rclcpp_components/register_node_macro.hpp"namespacecustom_action_cpp{classFibonacciActionClient:publicrclcpp::Node{public:usingFibonacci=custom_action_interfaces::action::Fibonacci;usingGoalHandleFibonacci=rclcpp_action::ClientGoalHandle;explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options){this->client_ptr_=rclcpp_action::create_client(this,"fibonacci");autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda);}voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptrfeedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);}private:rclcpp_action::Client::SharedPtrclient_ptr_;rclcpp::TimerBase::SharedPtrtimer_;};// class FibonacciActionClient}// namespace custom_action_cppRCLCPP_COMPONENTS_REGISTER_NODE(custom_action_cpp::FibonacciActionClient) + +Language: unknown +classFibonacciActionClient:publicrclcpp::Node + +Language: unknown +explicitFibonacciActionClient(constrclcpp::NodeOptions&options):Node("fibonacci_action_client",options) + +Language: unknown +this->client_ptr_=rclcpp_action::create_client(this,"fibonacci"); + +Language: unknown +autotimer_callback_lambda=[this](){returnthis->send_goal();};this->timer_=this->create_wall_timer(std::chrono::milliseconds(500),timer_callback_lambda); + +Language: unknown +voidsend_goal(){usingnamespacestd::placeholders;this->timer_->cancel();if(!this->client_ptr_->wait_for_action_server()){RCLCPP_ERROR(this->get_logger(),"Action server not available after waiting");rclcpp::shutdown();}autogoal_msg=Fibonacci::Goal();goal_msg.order=10;RCLCPP_INFO(this->get_logger(),"Sending goal");autosend_goal_options=rclcpp_action::Client::SendGoalOptions();send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}};send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptrfeedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<get_logger(),ss.str().c_str());};send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<get_logger(),ss.str().c_str());rclcpp::shutdown();};this->client_ptr_->async_send_goal(goal_msg,send_goal_options);} + +Language: unknown +send_goal_options.goal_response_callback=[this](constGoalHandleFibonacci::SharedPtr&goal_handle){if(!goal_handle){RCLCPP_ERROR(this->get_logger(),"Goal was rejected by server");}else{RCLCPP_INFO(this->get_logger(),"Goal accepted by server, waiting for result");}}; + +Language: unknown +send_goal_options.feedback_callback=[this](GoalHandleFibonacci::SharedPtr,conststd::shared_ptrfeedback){std::stringstreamss;ss<<"Next number in sequence received: ";for(autonumber:feedback->partial_sequence){ss<get_logger(),ss.str().c_str());}; + +Language: unknown +send_goal_options.result_callback=[this](constGoalHandleFibonacci::WrappedResult&result){switch(result.code){caserclcpp_action::ResultCode::SUCCEEDED:break;caserclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(this->get_logger(),"Goal was aborted");return;caserclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(this->get_logger(),"Goal was canceled");return;default:RCLCPP_ERROR(this->get_logger(),"Unknown result code");return;}std::stringstreamss;ss<<"Result received: ";for(autonumber:result.result->sequence){ss<get_logger(),ss.str().c_str());rclcpp::shutdown();}; + +Language: unknown +add_library(action_clientSHAREDsrc/fibonacci_action_client.cpp)target_include_directories(action_clientPRIVATE$$)target_compile_definitions(action_clientPRIVATE"CUSTOM_ACTION_CPP_BUILDING_DLL")ament_target_dependencies(action_client"custom_action_interfaces""rclcpp""rclcpp_action""rclcpp_components")rclcpp_components_register_node(action_clientPLUGIN"custom_action_cpp::FibonacciActionClient"EXECUTABLEfibonacci_action_client)install(TARGETSaction_clientARCHIVEDESTINATIONlibLIBRARYDESTINATIONlibRUNTIMEDESTINATIONbin) + +Language: unknown +colconbuild + +Language: unknown +ros2runcustom_action_cppfibonacci_action_client diff --git "a/exported_docs/ros2/Writing_an_action_server_and_client_(Python)\357\203\201.txt" "b/exported_docs/ros2/Writing_an_action_server_and_client_(Python)\357\203\201.txt" new file mode 100644 index 0000000..3e3ab57 --- /dev/null +++ "b/exported_docs/ros2/Writing_an_action_server_and_client_(Python)\357\203\201.txt" @@ -0,0 +1,137 @@ +Title: Writing an action server and client (Python) +URL: https://docs.ros.org/en/jazzy/Tutorials/Intermediate/Writing-an-Action-Server-Client/Py.html +Section: Installation +-------------------------------------------------------------------------------- + +Writing an action server and client (Python)Goal:Implement an action server and client in Python.Tutorial level:IntermediateTime:15 minutesContentsBackgroundPrerequisitesTasks1 Writing an action server2 Writing an action clientSummaryRelated contentBackgroundActions are a form of asynchronous communication in ROS 2.Action clientssend goal requests toaction servers.Action serverssend goal feedback and results toaction clients.PrerequisitesYou will need thecustom_action_interfacespackage and theFibonacci.actioninterface defined in the previous tutorial,Creating an action.Tasks1 Writing an action serverLet’s focus on writing an action server that computes the Fibonacci sequence +using the action we created in theCreating an actiontutorial.Until now, you’ve created packages and usedros2runto run your nodes. +To keep things simple in this tutorial, however, we’ll scope the action server to a single file. +If you’d like to see what a complete package for the actions tutorials looks like, check outaction_tutorials.Open a new file in your home directory, let’s call itfibonacci_action_server.py, +and add the following code:importrclpyfromrclpy.actionimportActionServerfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionServer(Node):def__init__(self):super().__init__('fibonacci_action_server')self._action_server=ActionServer(self,Fibonacci,'fibonacci',self.execute_callback)defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')result=Fibonacci.Result()returnresultdefmain(args=None):rclpy.init(args=args)fibonacci_action_server=FibonacciActionServer()rclpy.spin(fibonacci_action_server)if__name__=='__main__':main()Line 8 defines a classFibonacciActionServerthat is a subclass ofNode. +The class is initialized by calling theNodeconstructor, naming our nodefibonacci_action_server:super().__init__('fibonacci_action_server')In the constructor we also instantiate a new action server:self._action_server=ActionServer(self,Fibonacci,'fibonacci',self.execute_callback)An action server requires four arguments:A ROS 2 node to add the action client to:self.The type of the action:Fibonacci(imported in line 5).The action name:'fibonacci'.A callback function for executing accepted goals:self.execute_callback. +This callbackmustreturn a result message for the action type.We also define anexecute_callbackmethod in our class:defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')result=Fibonacci.Result()returnresultThis is the method that will be called to execute a goal once it is accepted.Let’s try running our action server:LinuxmacOSWindowspython3fibonacci_action_server.pypython3fibonacci_action_server.pypythonfibonacci_action_server.pyIn another terminal, we can use the command line interface to send a goal:ros2actionsend_goalfibonaccicustom_action_interfaces/action/Fibonacci"{order: 5}"In the terminal that is running the action server, you should see a logged message “Executing goal…” followed by a warning that the goal state was not set. +By default, if the goal handle state is not set in the execute callback it assumes theabortedstate.We can callsucceed()on the goal handle to indicate that the goal was successful:defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')goal_handle.succeed()result=Fibonacci.Result()returnresultNow if you restart the action server and send another goal, you should see the goal finished with the statusSUCCEEDED.Now let’s make our goal execution actually compute and return the requested Fibonacci sequence:defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')sequence=[0,1]foriinrange(1,goal_handle.request.order):sequence.append(sequence[i]+sequence[i-1])goal_handle.succeed()result=Fibonacci.Result()result.sequence=sequencereturnresultAfter computing the sequence, we assign it to the result message field before returning.Again, restart the action server and send another goal. +You should see the goal finish with the proper result sequence.1.2 Publishing feedbackOne of the nice things about actions is the ability to provide feedback to an action client during goal execution. +We can make our action server publish feedback for action clients by calling the goal handle’spublish_feedback()method.We’ll replace thesequencevariable, and use a feedback message to store the sequence instead. +After every update of the feedback message in the for-loop, we publish the feedback message and sleep for dramatic effect:importtimeimportrclpyfromrclpy.actionimportActionServerfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionServer(Node):def__init__(self):super().__init__('fibonacci_action_server')self._action_server=ActionServer(self,Fibonacci,'fibonacci',self.execute_callback)defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')feedback_msg=Fibonacci.Feedback()feedback_msg.partial_sequence=[0,1]foriinrange(1,goal_handle.request.order):feedback_msg.partial_sequence.append(feedback_msg.partial_sequence[i]+feedback_msg.partial_sequence[i-1])self.get_logger().info('Feedback:{0}'.format(feedback_msg.partial_sequence))goal_handle.publish_feedback(feedback_msg)time.sleep(1)goal_handle.succeed()result=Fibonacci.Result()result.sequence=feedback_msg.partial_sequencereturnresultdefmain(args=None):rclpy.init(args=args)fibonacci_action_server=FibonacciActionServer()rclpy.spin(fibonacci_action_server)if__name__=='__main__':main()After restarting the action server, we can confirm that feedback is now published by using the command line tool with the--feedbackoption:ros2actionsend_goal--feedbackfibonaccicustom_action_interfaces/action/Fibonacci"{order: 5}"2 Writing an action clientWe’ll also scope the action client to a single file. +Open a new file, let’s call itfibonacci_action_client.py, and add the following boilerplate code:importrclpyfromrclpy.actionimportActionClientfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')self._action_client=ActionClient(self,Fibonacci,'fibonacci')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()returnself._action_client.send_goal_async(goal_msg)defmain(args=None):rclpy.init(args=args)action_client=FibonacciActionClient()future=action_client.send_goal(10)rclpy.spin_until_future_complete(action_client,future)if__name__=='__main__':main()We’ve defined a classFibonacciActionClientthat is a subclass ofNode. +The class is initialized by calling theNodeconstructor, naming our nodefibonacci_action_client:super().__init__('fibonacci_action_client')Also in the class constructor, we create an action client using the custom action definition from the previous tutorial onCreating an action:self._action_client=ActionClient(self,Fibonacci,'fibonacci')We create anActionClientby passing it three arguments:A ROS 2 node to add the action client to:selfThe type of the action:FibonacciThe action name:'fibonacci'Our action client will be able to communicate with action servers of the same action name and type.We also define a methodsend_goalin theFibonacciActionClientclass:defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()returnself._action_client.send_goal_async(goal_msg)This method waits for the action server to be available, then sends a goal to the server. +It returns a future that we can later wait on.After the class definition, we define a functionmain()that initializes ROS 2 +and creates an instance of ourFibonacciActionClientnode. +It then sends a goal and waits until that goal has been completed.Finally, we callmain()in the entry point of our Python program.Let’s test our action client by first running the action server built earlier:LinuxmacOSWindowspython3fibonacci_action_server.pypython3fibonacci_action_server.pypythonfibonacci_action_server.pyIn another terminal, run the action client:LinuxmacOSWindowspython3fibonacci_action_client.pypython3fibonacci_action_client.pypythonfibonacci_action_client.pyYou should see messages printed by the action server as it successfully executes the goal:[INFO][fibonacci_action_server]:Executinggoal...[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1])[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1,2])[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1,2,3])[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1,2,3,5])# etc.The action client should start up, and then quickly finish. +At this point, we have a functioning action client, but we don’t see any results or get any feedback.2.1 Getting a resultSo we can send a goal, but how do we know when it is completed? +We can get the result information with a couple steps. +First, we need to get a goal handle for the goal we sent. +Then, we can use the goal handle to request the result.Here’s the complete code for this example:importrclpyfromrclpy.actionimportActionClientfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')self._action_client=ActionClient(self,Fibonacci,'fibonacci')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()self._send_goal_future=self._action_client.send_goal_async(goal_msg)self._send_goal_future.add_done_callback(self.goal_response_callback)defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback)defget_result_callback(self,future):result=future.result().resultself.get_logger().info('Result:{0}'.format(result.sequence))rclpy.shutdown()defmain(args=None):rclpy.init(args=args)action_client=FibonacciActionClient()action_client.send_goal(10)rclpy.spin(action_client)if__name__=='__main__':main()TheActionClient.send_goal_async()method returns a future to a goal handle. +First we register a callback for when the future is complete:self._send_goal_future.add_done_callback(self.goal_response_callback)Note that the future is completed when an action server accepts or rejects the goal request. +Let’s look at thegoal_response_callbackin more detail. +We can check to see if the goal was rejected and return early since we know there will be no result:defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')Now that we’ve got a goal handle, we can use it to request the result with the methodget_result_async(). +Similar to sending the goal, we will get a future that will complete when the result is ready. +Let’s register a callback just like we did for the goal response:self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback)In the callback, we log the result sequence and shutdown ROS 2 for a clean exit:defget_result_callback(self,future):result=future.result().resultself.get_logger().info('Result:{0}'.format(result.sequence))rclpy.shutdown()With an action server running in a separate terminal, go ahead and try running our Fibonacci action client!LinuxmacOSWindowspython3fibonacci_action_client.pypython3fibonacci_action_client.pypythonfibonacci_action_client.pyYou should see logged messages for the goal being accepted and the final result.2.2 Getting feedbackOur action client can send goals. +Nice! +But it would be great if we could get some feedback about the goals we send from the action server.Here’s the complete code for this example:importrclpyfromrclpy.actionimportActionClientfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')self._action_client=ActionClient(self,Fibonacci,'fibonacci')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()self._send_goal_future=self._action_client.send_goal_async(goal_msg,feedback_callback=self.feedback_callback)self._send_goal_future.add_done_callback(self.goal_response_callback)defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback)defget_result_callback(self,future):result=future.result().resultself.get_logger().info('Result:{0}'.format(result.sequence))rclpy.shutdown()deffeedback_callback(self,feedback_msg):feedback=feedback_msg.feedbackself.get_logger().info('Received feedback:{0}'.format(feedback.partial_sequence))defmain(args=None):rclpy.init(args=args)action_client=FibonacciActionClient()action_client.send_goal(10)rclpy.spin(action_client)if__name__=='__main__':main()Here’s the callback function for feedback messages:deffeedback_callback(self,feedback_msg):feedback=feedback_msg.feedbackself.get_logger().info('Received feedback:{0}'.format(feedback.partial_sequence))In the callback we get the feedback portion of the message and print thepartial_sequencefield to the screen.We need to register the callback with the action client. +This is achieved by additionally passing the callback to the action client when we send a goal:self._send_goal_future=self._action_client.send_goal_async(goal_msg,feedback_callback=self.feedback_callback)We’re all set. If we run our action client, you should see feedback being printed to the screen.SummaryIn this tutorial, you put together a Python action server and action client line by line, and configured them to exchange goals, feedback, and results.Related contentThere are several ways you could write an action server and client in Python; check out theminimal_action_serverandminimal_action_clientpackages in theros2/examplesrepo.For more detailed information about ROS actions, please refer to thedesign article. + +Code Examples: + +Language: unknown +importrclpyfromrclpy.actionimportActionServerfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionServer(Node):def__init__(self):super().__init__('fibonacci_action_server')self._action_server=ActionServer(self,Fibonacci,'fibonacci',self.execute_callback)defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')result=Fibonacci.Result()returnresultdefmain(args=None):rclpy.init(args=args)fibonacci_action_server=FibonacciActionServer()rclpy.spin(fibonacci_action_server)if__name__=='__main__':main() + +Language: unknown +super().__init__('fibonacci_action_server') + +Language: unknown +self._action_server=ActionServer(self,Fibonacci,'fibonacci',self.execute_callback) + +Language: unknown +defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')result=Fibonacci.Result()returnresult + +Language: unknown +python3fibonacci_action_server.py + +Language: unknown +python3fibonacci_action_server.py + +Language: unknown +pythonfibonacci_action_server.py + +Language: unknown +ros2actionsend_goalfibonaccicustom_action_interfaces/action/Fibonacci"{order: 5}" + +Language: unknown +defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')goal_handle.succeed()result=Fibonacci.Result()returnresult + +Language: unknown +defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')sequence=[0,1]foriinrange(1,goal_handle.request.order):sequence.append(sequence[i]+sequence[i-1])goal_handle.succeed()result=Fibonacci.Result()result.sequence=sequencereturnresult + +Language: unknown +importtimeimportrclpyfromrclpy.actionimportActionServerfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionServer(Node):def__init__(self):super().__init__('fibonacci_action_server')self._action_server=ActionServer(self,Fibonacci,'fibonacci',self.execute_callback)defexecute_callback(self,goal_handle):self.get_logger().info('Executing goal...')feedback_msg=Fibonacci.Feedback()feedback_msg.partial_sequence=[0,1]foriinrange(1,goal_handle.request.order):feedback_msg.partial_sequence.append(feedback_msg.partial_sequence[i]+feedback_msg.partial_sequence[i-1])self.get_logger().info('Feedback:{0}'.format(feedback_msg.partial_sequence))goal_handle.publish_feedback(feedback_msg)time.sleep(1)goal_handle.succeed()result=Fibonacci.Result()result.sequence=feedback_msg.partial_sequencereturnresultdefmain(args=None):rclpy.init(args=args)fibonacci_action_server=FibonacciActionServer()rclpy.spin(fibonacci_action_server)if__name__=='__main__':main() + +Language: unknown +ros2actionsend_goal--feedbackfibonaccicustom_action_interfaces/action/Fibonacci"{order: 5}" + +Language: unknown +importrclpyfromrclpy.actionimportActionClientfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')self._action_client=ActionClient(self,Fibonacci,'fibonacci')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()returnself._action_client.send_goal_async(goal_msg)defmain(args=None):rclpy.init(args=args)action_client=FibonacciActionClient()future=action_client.send_goal(10)rclpy.spin_until_future_complete(action_client,future)if__name__=='__main__':main() + +Language: unknown +super().__init__('fibonacci_action_client') + +Language: unknown +self._action_client=ActionClient(self,Fibonacci,'fibonacci') + +Language: unknown +defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()returnself._action_client.send_goal_async(goal_msg) + +Language: unknown +python3fibonacci_action_server.py + +Language: unknown +python3fibonacci_action_server.py + +Language: unknown +pythonfibonacci_action_server.py + +Language: unknown +python3fibonacci_action_client.py + +Language: unknown +python3fibonacci_action_client.py + +Language: unknown +pythonfibonacci_action_client.py + +Language: unknown +[INFO][fibonacci_action_server]:Executinggoal...[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1])[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1,2])[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1,2,3])[INFO][fibonacci_action_server]:Feedback:array('i',[0,1,1,2,3,5])# etc. + +Language: unknown +importrclpyfromrclpy.actionimportActionClientfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')self._action_client=ActionClient(self,Fibonacci,'fibonacci')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()self._send_goal_future=self._action_client.send_goal_async(goal_msg)self._send_goal_future.add_done_callback(self.goal_response_callback)defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback)defget_result_callback(self,future):result=future.result().resultself.get_logger().info('Result:{0}'.format(result.sequence))rclpy.shutdown()defmain(args=None):rclpy.init(args=args)action_client=FibonacciActionClient()action_client.send_goal(10)rclpy.spin(action_client)if__name__=='__main__':main() + +Language: unknown +self._send_goal_future.add_done_callback(self.goal_response_callback) + +Language: unknown +defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)') + +Language: unknown +self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback) + +Language: unknown +defget_result_callback(self,future):result=future.result().resultself.get_logger().info('Result:{0}'.format(result.sequence))rclpy.shutdown() + +Language: unknown +python3fibonacci_action_client.py + +Language: unknown +python3fibonacci_action_client.py + +Language: unknown +pythonfibonacci_action_client.py + +Language: unknown +importrclpyfromrclpy.actionimportActionClientfromrclpy.nodeimportNodefromcustom_action_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')self._action_client=ActionClient(self,Fibonacci,'fibonacci')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=orderself._action_client.wait_for_server()self._send_goal_future=self._action_client.send_goal_async(goal_msg,feedback_callback=self.feedback_callback)self._send_goal_future.add_done_callback(self.goal_response_callback)defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback)defget_result_callback(self,future):result=future.result().resultself.get_logger().info('Result:{0}'.format(result.sequence))rclpy.shutdown()deffeedback_callback(self,feedback_msg):feedback=feedback_msg.feedbackself.get_logger().info('Received feedback:{0}'.format(feedback.partial_sequence))defmain(args=None):rclpy.init(args=args)action_client=FibonacciActionClient()action_client.send_goal(10)rclpy.spin(action_client)if__name__=='__main__':main() + +Language: unknown +deffeedback_callback(self,feedback_msg):feedback=feedback_msg.feedbackself.get_logger().info('Received feedback:{0}'.format(feedback.partial_sequence)) + +Language: unknown +self._send_goal_future=self._action_client.send_goal_async(goal_msg,feedback_callback=self.feedback_callback) diff --git "a/exported_docs/ros2/ament_cmake_user_documentation\357\203\201.txt" "b/exported_docs/ros2/ament_cmake_user_documentation\357\203\201.txt" new file mode 100644 index 0000000..fc0ded6 --- /dev/null +++ "b/exported_docs/ros2/ament_cmake_user_documentation\357\203\201.txt" @@ -0,0 +1,165 @@ +Title: ament_cmake user documentation +URL: https://docs.ros.org/en/jazzy/How-To-Guides/Ament-CMake-Documentation.html +Section: Installation +-------------------------------------------------------------------------------- + +ament_cmake user documentationament_cmakeis the build system for CMake based packages in ROS 2 (in particular, it will be used for most C/C++ projects). +It is a set of scripts enhancing CMake and adding convenience functionality for package authors. +Before usingament_cmake, it is very helpful to know the basics ofCMake. +An official tutorial can be foundhere.Table of ContentsBasicsBasic project outlineCompiler and linker optionsFinding dependenciesAdding targetsLinking to dependenciesInstallingLinting and TestingLintingTestingExtending amentAdding a function/macro to amentAdding to extension pointsAdding extension pointsAdding resourcesThe ament index explainedQuerying the ament indexAdding to the ament indexBasicsA basic CMake outline can be produced usingros2pkgcreateon the command line. +The build information is then gathered in two files: thepackage.xmland theCMakeLists.txt, which must be in the same directory. +Thepackage.xmlmust contain all dependencies and a bit of metadata to allow colcon to find the correct build order for your packages, to install the required dependencies in CI, and to provide the information for a release withbloom. +TheCMakeLists.txtcontains the commands to build and package executables and libraries and will be the main focus of this document.Basic project outlineThe basic outline of theCMakeLists.txtof an ament package contains:cmake_minimum_required(VERSION3.8)project(my_project)ament_package()The argument toprojectwill be the package name and must be identical to the package name in thepackage.xml.The project setup is done byament_package()and this call must occur exactly once per package.ament_package()installs thepackage.xml, registers the package with the ament index, and installs configuration (and possibly target) files for CMake so that it can be found by other packages usingfind_package. +Sinceament_package()gathers a lot of information from theCMakeLists.txtit should be the last call in yourCMakeLists.txt.ament_packagecan be given additional arguments:CONFIG_EXTRAS: a list of CMake files (.cmakeor.cmake.intemplates expanded byconfigure_file()) which should be available to clients of the package. +For an example of when to use these arguments, see the discussion inAdding resources. +For more information on how to use template files, seethe official documentation.CONFIG_EXTRAS_POST: same asCONFIG_EXTRAS, but the order in which the files are added differs. +WhileCONFIG_EXTRASfiles are included before the files generated for theament_export_*calls the files fromCONFIG_EXTRAS_POSTare included afterwards.Instead of adding toament_package, you can also add to the variable${PROJECT_NAME}_CONFIG_EXTRASand${PROJECT_NAME}_CONFIG_EXTRAS_POSTwith the same effect. +The only difference is again the order in which the files are added with the following total order:files added byCONFIG_EXTRASfiles added by appending to${PROJECT_NAME}_CONFIG_EXTRASfiles added by appending to${PROJECT_NAME}_CONFIG_EXTRAS_POSTfiles added byCONFIG_EXTRAS_POSTCompiler and linker optionsROS 2 targets compilers which comply with the C++17 and C99 standard. +Newer versions might be targeted in the future and are referencedhere. +Therefore it is customary to set the corresponding CMake flags:if(NOTCMAKE_C_STANDARD)set(CMAKE_C_STANDARD99)endif()if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD17)endif()To keep the code clean, compilers should throw warnings for questionable code and these warnings should be fixed.It is recommended to at least cover the following warning levels:For Visual Studio: the defaultW1warningsFor GCC and Clang:-Wall-Wextra-Wpedanticare highly recommended and-Wshadowis advisableIt is currently recommended to useadd_compile_optionsto add these options for all targets. +This avoids cluttering the code with target-based compile options for all executables, libraries, and tests:if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()Finding dependenciesMostament_cmakeprojects will have dependencies on other packages. +In CMake, this is accomplished by callingfind_package. +For instance, if your package depends onrclcpp, then theCMakeLists.txtfile should contain:find_package(rclcppREQUIRED)NoteIt should never be necessary tofind_packagea library that is not explicitly needed but is a dependency of another dependency that is explicitly needed. +If that is the case, file a bug against the corresponding package.Adding targetsIn CMake nomenclature,targetsare the artifacts that this project will create. +Either libraries or executables can be created, and a single project can contain zero or many of each of them.LibrariesExecutablesThese are created with a call toadd_library, which should contain both the name of the target and the source files that should be compiled to create the library.With the separation of header files and implementation in C/C++, it is not usually necessary to add header files as arguments toadd_library.The following best practice is proposed:Put all headers which should be usable by clients of this library (and therefore must be installed) into a subdirectory of theincludefolder named like the package, while all other files (.c/.cppand header files which should not be exported) are inside thesrcfolderOnly.c/.cppfiles are explicitly referenced in the call toadd_libraryFind headers to your librarymy_libraryviatarget_include_directories(my_libraryPUBLIC"$""$")This adds all files in the folder${CMAKE_CURRENT_SOURCE_DIR}/includeto the public interface during build time and all files in the include folder (relative to${CMAKE_INSTALL_DIR}) when being installed.ros2pkgcreatecreates a package layout that follows these rules.NoteSince Windows is one of the officially supported platforms, to have maximum impact, any package should also build on Windows. +The Windows library format enforces symbol visibility; that is, every symbol which should be used from a client has to be explicitly exported by the library (and symbols need to be implicitly imported).Since GCC and Clang builds do not generally do this, it is advised to use the logic inthe GCC wiki. +To use it for a package calledmy_library:Copy the logic in the link into a header file calledvisibility_control.hpp.ReplaceDLLbyMY_LIBRARY(for an example, see visibility control ofrviz_rendering).Use the macros “MY_LIBRARY_PUBLIC” for all symbols you need to export (i.e. classes or functions).In the projectCMakeLists.txtuse:target_compile_definitions(my_libraryPRIVATE"MY_LIBRARY_BUILDING_LIBRARY")For more details, seeWindows Symbol Visibility in the Windows Tips and Tricks document.These should be created with a call toadd_executable, which should contain both the name of the target and the source files that should be compiled to create the executable. +The executable may also have to be linked with any libraries created in this package by usingtarget_link_libraries.Since executables aren’t generally used by clients as a library, no header files need to be put in theincludedirectory.In the case that a package has both libraries and executables, make sure to combine the advice from both “Libraries” and “Executables” above.Linking to dependenciesThere are two ways to link your targets against a dependency.The first and recommended way is to use the ament macroament_target_dependencies. +As an example, suppose we want to linkmy_libraryagainst the linear algebra library Eigen3.find_package(Eigen3REQUIRED)ament_target_dependencies(my_libraryPUBLICEigen3)It includes the necessary headers and libraries and their dependencies to be correctly found by the project.The second way is to usetarget_link_libraries.Modern CMake prefers to use only targets, exporting and linking against them. +CMake targets may be namespaced, similar to C++. +Prefer to use the namespaced targets if they are available. +For instance,Eigen3defines the targetEigen3::Eigen.In the example of Eigen3, the call should then look liketarget_link_libraries(my_libraryPUBLICEigen3::Eigen)This will also include necessary headers, libraries and their dependencies. +Note that this dependency must have been previously discovered via a call tofind_package.InstallingLibrariesExecutablesWhen building a reusable library, some information needs to be exported for downstream packages to easily use it.First, install the headers files which should be available to clients. +The include directory is custom to support overlays incolcon; seehttps://colcon.readthedocs.io/en/released/user/overriding-packages.html#install-headers-to-a-unique-include-directoryfor more information.install(DIRECTORYinclude/DESTINATIONinclude/${PROJECT_NAME})Next, install the targets and create the export target (export_${PROJECT_NAME}) that other code will use to find this package. +Note that you can use a singleinstallcall to install all of the libraries in the project.install(TARGETSmy_libraryEXPORTexport_${PROJECT_NAME}LIBRARYDESTINATIONlibARCHIVEDESTINATIONlibRUNTIMEDESTINATIONbin)ament_export_targets(export_${PROJECT_NAME}HAS_LIBRARY_TARGET)ament_export_dependencies(some_dependency)Here is what’s happening in the snippet above:Theament_export_targetsmacro exports the targets for CMake. +This is necessary to allow your library’s clients to use thetarget_link_libraries(clientPRIVATEmy_library::my_library)syntax. +If the export set includes a library, add the optionHAS_LIBRARY_TARGETtoament_export_targets, which adds potential libraries to environment variables.Theament_export_dependenciesexports dependencies to downstream packages. +This is necessary so that the user of the library does not have to callfind_packagefor those dependencies, too.WarningCallingament_export_targets,ament_export_dependencies, or other ament commands from a CMake subdirectory will not work as expected. +This is because the CMake subdirectory has no way of setting necessary variables in the parent scope whereament_packageis called.NoteWindows DLLs are treated as runtime artifacts and installed into theRUNTIMEDESTINATIONfolder. +It is therefore advised to keep theRUNTIMEinstall even when developing libraries on Unix based systems.TheEXPORTnotation of the install call requires additional attention: +It installs the CMake files for themy_librarytarget. +It must be named exactly the same as the argument inament_export_targets. +To ensure that it can be used viaament_target_dependencies, it should not be named exactly the same as the library name, but instead should have a prefix likeexport_(as shown above).All install paths are relative toCMAKE_INSTALL_PREFIX, which is already set correctly by colcon/ament.There are two additional functions which are available, but are superfluous for target based installs:ament_export_include_directories("include/${PROJECT_NAME}")ament_export_libraries(my_library)The first macro marks the directory of the exported include directories. +The second macro marks the location of the installed library (this is done by theHAS_LIBRARY_TARGETargument in the call toament_export_targets). +These should only be used if the downstream projects can’t or don’t want to use CMake target based dependencies.Some of the macros can take different types of arguments for non-target exports, but since the recommended way for modern Make is to use targets, we will not cover them here. +Documentation of these options can be found in the source code itself.When installing an executable, the following stanzamust be followed exactlyfor the rest of the ROS tooling to find it:install(TARGETSmy_exeDESTINATIONlib/${PROJECT_NAME})In the case that a package has both libraries and executables, make sure to combine the advice from both “Libraries” and “Executables” above.Linting and TestingIn order to separate testing from building the library with colcon, wrap all calls to linters and tests in a conditional:if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest()endif()LintingIt’s advised to use the combined call fromament_lint_auto:find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies()This will run linters as defined in thepackage.xml. +It is recommended to use the set of linters defined by the packageament_lint_common. +The individual linters included there, as well as their functions, can be seen in theament_lint_common docs.Linters provided by ament can also be added separately, instead of runningament_lint_auto. +One example of how to do so can be found in theament_cmake_lint_cmake documentation.TestingAment contains CMake macros to simplify setting up GTests. Call:find_package(ament_cmake_gtest)ament_add_gtest(some_test)to add a GTest. +This is then a regular target which can be linked against other libraries (such as the project library). +The macros have additional parameters:APPEND_ENV: append environment variables. +For instance you can add to the ament prefix path by calling:find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(some_testAPPEND_ENVPATH=some/addtional/path/for/testing/resources)APPEND_LIBRARY_DIRS: append libraries so that they can be found by the linker at runtime. +This can be achieved by setting environment variables likePATHon Windows andLD_LIBRARY_PATHon Linux, but this makes the call platform specific.ENV: set environment variables (same syntax asAPPEND_ENV).TIMEOUT: set a test timeout in second. The default for GTests is 60 seconds. For example:ament_add_gtest(some_testTIMEOUT120)SKIP_TEST: skip this test (will be shown as “passed” in the console output).SKIP_LINKING_MAIN_LIBRARIES: Don’t link against GTest.WORKING_DIRECTORY: set the working directory for the test.The default working directory otherwise is theCMAKE_CURRENT_BINARY_DIR, which is described in theCMake documentation.Similarly, there is a CMake macro to set up GTest including GMock:find_package(ament_cmake_gmockREQUIRED)ament_add_gmock(some_test)It has the same additional parameters asament_add_gtest.Extending amentIt is possible to register additional macros/functions withament_cmakeand extend it in several ways.Adding a function/macro to amentExtending ament will often times mean that you want to have some functions available to other packages. +The best way to provide the macro to client packages is to register it with ament.This can be done by appending the${PROJECT_NAME}_CONFIG_EXTRASvariable, which is used byament_package()vialist(APPEND${PROJECT_NAME}_CONFIG_EXTRASpath/to/file.cmake"other/pathto/file.cmake")Alternatively, you can directly add the files to theament_package()call:ament_package(CONFIG_EXTRASpath/to/file.cmakeother/pathto/file.cmake)Adding to extension pointsIn addition to simple files with functions that can be used in other packages, you can also add extensions to ament. +Those extensions are scripts which are executed with the function which defines the extension point. +The most common use-case for ament extensions is probably registering rosidl message generators: +When writing a generator, you normally want to generate all messages and services with your generator also without modifying the code for the message/service definition packages. +This is possible by registering the generator as an extension torosidl_generate_interfaces.As an example, seeament_register_extension("rosidl_generate_interfaces""rosidl_generator_cpp""rosidl_generator_cpp_generate_interfaces.cmake")which registers the macrorosidl_generator_cpp_generate_interfaces.cmakefor the packagerosidl_generator_cppto the extension pointrosidl_generate_interfaces. +When the extension point gets executed, this will trigger the execution of the scriptrosidl_generator_cpp_generate_interfaces.cmakehere. +In particular, this will call the generator whenever the functionrosidl_generate_interfacesgets executed.The most important extension point for generators, aside fromrosidl_generate_interfaces, isament_package, which will simply execute scripts with theament_package()call. +This extension point is useful when registering resources (see below).ament_register_extensionis a function which takes exactly three arguments:extension_point: The name of the extension point (most of the time this will be one ofament_packageorrosidl_generate_interfaces)package_name: The name of the package containing the CMake file (i.e. the project name of the project where the file is written to)cmake_filename: The CMake file executed when the extension point is runNoteIt is possible to define custom extension points in a similar manner toament_packageandrosidl_generate_interfaces, but this should hardly be necessary.Adding extension pointsVery rarely, it might be interesting to define a new extension point to ament.Extension points can be registered within a macro so that all extensions will be executed when the corresponding macro is called. +To do so:Define and document a name for your extension (e.g.my_extension_point), which is the name passed to theament_register_extensionmacro when using the extension point.In the macro/function which should execute the extensions call:ament_execute_extensions(my_extension_point)Ament extensions work by defining a variable containing the name of the extension point and filling it with the macros to be executed. +Upon callingament_execute_extensions, the scripts defined in the variable are then executed one after another.Adding resourcesEspecially when developing plugins or packages which allow plugins it is often essential to add resources to one ROS package from another (e.g. a plugin). +Examples can be plugins for tools using the pluginlib.This can be achieved using the ament index (also called “resource index”).The ament index explainedFor details on the design and intentions, seehereIn principle, the ament index is contained in a folder within the install/share folder of your package. +It contains shallow subfolders named after different types of resources. +Within the subfolder, each package providing said resource is referenced by name with a “marker file”. +The file may contain whatever content necessary to obtain the resources, e.g. relative paths to the installation directories of the resource, it may also be simply empty.To give an example, consider providing display plugins for RViz: +When providing RViz plugins in a project namedmy_rviz_displayswhich will be read by the pluginlib, you will provide aplugin_description.xmlfile, which will be installed and used by the pluginlib to load the plugins. +To achieve this, the plugin_description.xml is registered as a resource in the resource_index viapluginlib_export_plugin_description_file(rviz_commonplugins_description.xml)When runningcolconbuild, this installs a filemy_rviz_displaysinto a subfolderrviz_common__pluginlib__plugininto the resource_index. +Pluginlib factories within rviz_common will know to gather information from all folders namedrviz_common__pluginlib__pluginfor packages that export plugins. +The marker file for pluginlib factories contains an install-folder relative path to theplugins_description.xmlfile (and the name of the library as marker file name). +With this information, the pluginlib can load the library and know which plugins to load from theplugin_description.xmlfile.As a second example, consider the possibility to let your own RViz plugins use your own custom meshes. +Meshes get loaded at startup time so that the plugin owner does not have to deal with it, but this implies RViz has to know about the meshes. +To achieve this, RViz provides a function:register_rviz_ogre_media_exports(DIRECTORIES)This registers the directories as an ogre_media resource in the ament index. +In short, it installs a file named after the project which calls the function into a subfolder calledrviz_ogre_media_exports. +The file contains the install folder relative paths to the directories listed in the macros. +On startup time, RViz can now search for all folders calledrviz_ogre_media_exportsand load resources in all folders provided. +These searches are done usingament_index_cpp(orament_index_pyfor Python packages).In the following sections we will explore how to add your own resources to the ament index and provide best practices for doing so.Querying the ament indexIf necessary, it is possible to query the ament index for resources via CMake. +To do so, there are three functions:ament_index_has_resource: Obtain a prefix path to the resource if it exists with the following parameters:var: the output parameter: fill this variable with FALSE if the resource does not exist or the prefix path to the resource otherwiseresource_type: The type of the resource (e.g.rviz_common__pluginlib__plugin)resource_name: The name of the resource which usually amounts to the name of the package having added the resource of type resource_type (e.g.rviz_default_plugins)ament_index_get_resource: Obtain the content of a specific resource, i.e. the contents of the marker file in the ament index.var: the output parameter: filled with the content of the resource marker file if it exists.resource_type: The type of the resource (e.g.rviz_common__pluginlib__plugin)resource_name: The name of the resource which usually amounts to the name of the package having added the resource of type resource_type (e.g.rviz_default_plugins)PREFIX_PATH: The prefix path to search for (usually, the defaultament_index_get_prefix_path()will be enough).Note thatament_index_get_resourcewill throw an error if the resource does not exist, so it might be necessary to check usingament_index_has_resource.ament_index_get_resources: Get all packages which registered resources of a specific type from the indexvar: Output parameter: filled with a list of names of all packages which registered a resource of resource_typeresource_type: The type of the resource (e.g.rviz_common__pluginlib__plugin)PREFIX_PATH: The prefix path to search for (usually, the defaultament_index_get_prefix_path()will be enough).Adding to the ament indexDefining a resource requires two bits of information:a name for the resource which must be unique,a layout of the marker file, which can be anything and could also be empty (this is true for instance for the “package” resource marking a ROS 2 package)For the RViz mesh resource, the corresponding choices were:rviz_ogre_media_exportsas name of the resource,install path relative paths to all folders containing resources. This will already enable you to write the logic for using the corresponding resource in your package.To allow users to easily register resources for your package, you should furthermore provide macros or functions such as the pluginlib function orrviz_ogre_media_exportsfunction.To register a resource, use the ament functionament_index_register_resource. +This will create and install the marker files in the resource_index. +As an example, the corresponding call forrviz_ogre_media_exportsis the following:ament_index_register_resource(rviz_ogre_media_exportsCONTENT${OGRE_MEDIA_RESOURCE_FILE})This installs a file named like${PROJECT_NAME}into a folderrviz_ogre_media_exportsinto the resource_index with content given by variable${OGRE_MEDIA_RESOURCE_FILE}. +The macro has a number of parameters that can be useful:the first (unnamed) parameter is the name of the resource, which amounts to the name of the folder in the resource_indexCONTENT: The content of the marker file as string. This could be a list of relative paths, etc.CONTENTcannot be used together withCONTENT_FILE.CONTENT_FILE: The path to a file which will be use to create the marker file. The file can be a plain file or a template file expanded withconfigure_file().CONTENT_FILEcannot be used together withCONTENT.PACKAGE_NAME: The name of the package/library exporting the resource, which amounts to the name of the marker file. Defaults to${PROJECT_NAME}.AMENT_INDEX_BINARY_DIR: The base path of the generated ament index. Unless really necessary, always use the default${CMAKE_BINARY_DIR}/ament_cmake_index.SKIP_INSTALL: Skip installing the marker file.Since only one marker file exists per package, it is usually a problem if the CMake function/macro gets called twice by the same project. +However, for large projects it might be best to split up calls registering resources.Therefore, it is best practice to let a macro registering a resource such asregister_rviz_ogre_media_exports.cmakeonly fill some variables. +The real call toament_index_register_resourcecan then be added within an ament extension toament_package. +Since there must only ever be one call toament_packageper project, there will always only be one place where the resource gets registered. +In the case ofrviz_ogre_media_exportsthis amounts to the following strategy:The macroregister_rviz_ogre_media_exportstakes a list of folders and appends them to a variable calledOGRE_MEDIA_RESOURCE_FILE.Another macro calledregister_rviz_ogre_media_exports_hookcallsament_index_register_resourceif${OGRE_MEDIA_RESOURCE_FILE}is non-empty.Theregister_rviz_ogre_media_exports_hook.cmakefile is registered as an ament extension in a third fileregister_rviz_ogre_media_exports_hook-extras.cmakevia callingament_register_extension("ament_package""rviz_rendering""register_rviz_ogre_media_exports_hook.cmake")The filesregister_rviz_ogre_media_exports.cmakeandregister_rviz_ogre_media_exports_hook-extra.cmakeare registered asCONFIG_EXTRAwithament_package(). + +Code Examples: + +Language: unknown +cmake_minimum_required(VERSION3.8)project(my_project)ament_package() + +Language: unknown +if(NOTCMAKE_C_STANDARD)set(CMAKE_C_STANDARD99)endif()if(NOTCMAKE_CXX_STANDARD)set(CMAKE_CXX_STANDARD17)endif() + +Language: unknown +if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif() + +Language: unknown +find_package(rclcppREQUIRED) + +Language: unknown +target_include_directories(my_libraryPUBLIC"$""$") + +Language: unknown +target_compile_definitions(my_libraryPRIVATE"MY_LIBRARY_BUILDING_LIBRARY") + +Language: unknown +find_package(Eigen3REQUIRED)ament_target_dependencies(my_libraryPUBLICEigen3) + +Language: unknown +target_link_libraries(my_libraryPUBLICEigen3::Eigen) + +Language: unknown +install(DIRECTORYinclude/DESTINATIONinclude/${PROJECT_NAME}) + +Language: unknown +install(TARGETSmy_libraryEXPORTexport_${PROJECT_NAME}LIBRARYDESTINATIONlibARCHIVEDESTINATIONlibRUNTIMEDESTINATIONbin)ament_export_targets(export_${PROJECT_NAME}HAS_LIBRARY_TARGET)ament_export_dependencies(some_dependency) + +Language: unknown +ament_export_include_directories("include/${PROJECT_NAME}")ament_export_libraries(my_library) + +Language: unknown +install(TARGETSmy_exeDESTINATIONlib/${PROJECT_NAME}) + +Language: unknown +if(BUILD_TESTING)find_package(ament_cmake_gtestREQUIRED)ament_add_gtest()endif() + +Language: unknown +find_package(ament_lint_autoREQUIRED)ament_lint_auto_find_test_dependencies() + +Language: unknown +find_package(ament_cmake_gtest)ament_add_gtest(some_test) + +Language: unknown +find_package(ament_cmake_gtestREQUIRED)ament_add_gtest(some_testAPPEND_ENVPATH=some/addtional/path/for/testing/resources) + +Language: unknown +ament_add_gtest(some_testTIMEOUT120) + +Language: unknown +find_package(ament_cmake_gmockREQUIRED)ament_add_gmock(some_test) + +Language: unknown +list(APPEND${PROJECT_NAME}_CONFIG_EXTRASpath/to/file.cmake"other/pathto/file.cmake") + +Language: unknown +ament_package(CONFIG_EXTRASpath/to/file.cmakeother/pathto/file.cmake) + +Language: unknown +ament_register_extension("rosidl_generate_interfaces""rosidl_generator_cpp""rosidl_generator_cpp_generate_interfaces.cmake") + +Language: unknown +ament_execute_extensions(my_extension_point) + +Language: unknown +pluginlib_export_plugin_description_file(rviz_commonplugins_description.xml) + +Language: unknown +register_rviz_ogre_media_exports(DIRECTORIES) + +Language: unknown +ament_index_register_resource(rviz_ogre_media_exportsCONTENT${OGRE_MEDIA_RESOURCE_FILE}) + +Language: unknown +ament_register_extension("ament_package""rviz_rendering""register_rviz_ogre_media_exports_hook.cmake") diff --git "a/exported_docs/ros2/eProsima_Fast_DDS\357\203\201.txt" "b/exported_docs/ros2/eProsima_Fast_DDS\357\203\201.txt" new file mode 100644 index 0000000..f7f5a02 --- /dev/null +++ "b/exported_docs/ros2/eProsima_Fast_DDS\357\203\201.txt" @@ -0,0 +1,36 @@ +Title: eProsima Fast DDS +URL: https://docs.ros.org/en/jazzy/Installation/DDS-Implementations/Working-with-eProsima-Fast-DDS.html +Section: Installation +-------------------------------------------------------------------------------- + +eProsima Fast DDSeProsima Fast DDS is a complete open-source DDS implementation for real time embedded architectures and operating systems. +See also:https://www.eprosima.com/index.php/products-all/eprosima-fast-ddsPrerequisitesHaverosdep installed.Install packagesThe easiest way is to install from ROS 2 apt repository.sudoaptinstallros-jazzy-rmw-fastrtps-cppBuild from source codeBuilding from source code is also another way to install.First, clone Fast DDS and rmw_fastrtps in the ROS 2 workspace source directory.cdros2_ws/src +gitclonehttps://github.com/ros2/rmw_fastrtpsros2/rmw_fastrtps-bjazzy +gitclonehttps://github.com/eProsima/Fast-DDSeProsima/fastrtpsThen, install necessary packages for Fast DDS.cd.. +rosdepinstall--fromsrc-iFinally, run colcon build.colconbuild--symlink-installSwitch to rmw_fastrtpsThe eProsima Fast DDS RMW can be selected by specifying the environment variable:exportRMW_IMPLEMENTATION=rmw_fastrtps_cppSee also:Working with multiple RMW implementationsRun the talker and listenerNow runtalkerandlistenerto test Fast DDS.ros2rundemo_nodes_cpptalkerros2rundemo_nodes_cpplistener + +Code Examples: + +Language: unknown +sudoaptinstallros-jazzy-rmw-fastrtps-cpp + +Language: unknown +cdros2_ws/src +gitclonehttps://github.com/ros2/rmw_fastrtpsros2/rmw_fastrtps-bjazzy +gitclonehttps://github.com/eProsima/Fast-DDSeProsima/fastrtps + +Language: unknown +cd.. +rosdepinstall--fromsrc-i + +Language: unknown +colconbuild--symlink-install + +Language: unknown +exportRMW_IMPLEMENTATION=rmw_fastrtps_cpp + +Language: unknown +ros2rundemo_nodes_cpptalker + +Language: unknown +ros2rundemo_nodes_cpplistener diff --git "a/exported_docs/ros2/macOS_(source)\357\203\201.txt" "b/exported_docs/ros2/macOS_(source)\357\203\201.txt" new file mode 100644 index 0000000..1bb0880 --- /dev/null +++ "b/exported_docs/ros2/macOS_(source)\357\203\201.txt" @@ -0,0 +1,61 @@ +Title: macOS (source) +URL: https://docs.ros.org/en/jazzy/Installation/Alternatives/macOS-Development-Setup.html +Section: Installation +-------------------------------------------------------------------------------- + +macOS (source)Table of ContentsSystem requirementsSystem setupInstall prerequisitesDisable System Integrity Protection (SIP)Build ROS 2Get ROS 2 codeInstall additional RMW implementations (optional)Build the code in the workspaceSetup environmentTry some examplesNext stepsUse the ROS 1 bridge (optional)Stay up to dateTroubleshootUninstallSystem requirementsWe currently support macOS Mojave (10.14).System setupInstall prerequisitesYou need the following things installed to build ROS 2:XcodeIf you don’t already have it installed, install [Xcode](https://apps.apple.com/app/xcode/id497799835).Note: Versions of Xcode later than 11.3.1 can no longer be installed on macOS Mojave, so you will need to install an older version manually, see:https://stackoverflow.com/a/61046761Also, if you don’t already have it installed, install the Command Line Tools:xcode-select--install# This command will not succeed if you have not installed Xcode.appsudoxcode-select--switch/Applications/Xcode.app/Contents/Developer# If you installed Xcode.app manually, you need to either open it or run:sudoxcodebuild-license# To accept the Xcode.app licensebrew(needed to install more stuff; you probably already have this):Follow installation instructions athttp://brew.sh/Optional: Check thatbrewis happy with your system configuration by running:brewdoctorFix any problems that it identifies.Usebrewto install more stuff:brewinstallasioassimpbisonbulletcmakeconsole_bridgecppcheck\cuniteigenfreetypegraphvizopencvopensslorocos-kdlpcrepoco\pyqt@5pythonqt@5sipspdlogtinyxml2Setup some environment variables:# Add the openssl dir for DDS-Security# if you are using BASH, then replace '.zshrc' with '.bashrc'echo"export OPENSSL_ROOT_DIR=$(brew--prefixopenssl)">>~/.zshrc# Add the Qt directory to the PATH and CMAKE_PREFIX_PATHexportCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$(brew--prefixqt@5)exportPATH=$PATH:$(brew--prefixqt@5)/binUsepython3-mpip(justpipmay install Python3 or Python2) to install more stuff:python3-mpipinstall--upgradepip + +python3-mpipinstall-U\--config-settings="--global-option=build_ext"\--config-settings="--global-option=-I$(brew--prefixgraphviz)/include/"\--config-settings="--global-option=-L$(brew--prefixgraphviz)/lib/"\argcompletecatkin_pkgcolcon-common-extensionscoverage\cryptographyempyflake8flake8-blind-except==0.1.1flake8-builtins\flake8-class-newlineflake8-comprehensionsflake8-deprecated\flake8-docstringsflake8-import-orderflake8-quotes\importlib-metadatajsonschemalark==1.1.1lxmlmatplotlibmockmypy==0.931netifaces\nosepep8psutilpydocstylepydotpygraphvizpyparsing==2.4.7\pytest-mockrosdeprosdistrosetuptools==59.6.0vcstoolPlease ensure that the$PATHenvironment variable contains the install location of the binaries ($(brew--prefix)/bin)Optional: if you want to build the ROS 1<->2 bridge, then you must also install ROS 1:Start with the normal install instructions:http://wiki.ros.org/kinetic/Installation/OSX/Homebrew/SourceWhen you get to the step where you callrosinstall_generatorto get the source code, here’s an alternate invocation that brings in just the minimum required to produce a useful bridge:rosinstall_generatorcatkincommon_msgsroscpprosmsg--rosdistrokinetic--deps--wet-only--tar>kinetic-ros2-bridge-deps.rosinstall +wstoolinit-j8srckinetic-ros2-bridge-deps.rosinstallOtherwise, just follow the normal instructions, then source the resultinginstall_isolated/setup.bashbefore proceeding here to build ROS 2.Disable System Integrity Protection (SIP)macOS/OS X versions >=10.11 have System Integrity Protection enabled by default. +So that SIP doesn’t prevent processes from inheriting dynamic linker environment variables, such asDYLD_LIBRARY_PATH, you’ll need to disable itfollowing these instructions.Build ROS 2Get ROS 2 codeCreate a workspace and clone all repos:mkdir-p~/ros2_jazzy/srccd~/ros2_jazzy +vcsimport--inputhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repossrcInstall additional RMW implementations (optional)The default middleware that ROS 2 uses isFastDDS, but the middleware (RMW) can be replaced at build or runtime. +See theguideon how to work with multiple RMWs.Build the code in the workspaceRun thecolcontool to build everything (more on usingcolconinthis tutorial):cd~/ros2_jazzy/ +colconbuild--symlink-install--packages-skip-by-deppython_qt_bindingNote: due to an unresolved issue with SIP, Qt@5, and PyQt5, we need to disablepython_qt_bindingto have the build succeed. +This will be removed when the issue is resolved, see:https://github.com/ros-visualization/python_qt_binding/issues/103Setup environmentSource the ROS 2 setup file:.~/ros2_jazzy/install/setup.zshThis will automatically set up the environment for any DDS vendors that support was built for.Try some examplesIn one terminal, set up the ROS 2 environment as described above and then run a C++talker:ros2rundemo_nodes_cpptalkerIn another terminal source the setup file and then run a Pythonlistener:ros2rundemo_nodes_pylistenerYou should see thetalkersaying that it’sPublishingmessages and thelistenersayingIheardthose messages. +This verifies both the C++ and Python APIs are working properly. +Hooray!Next stepsContinue with thetutorials and demosto configure your environment, create your own workspace and packages, and learn ROS 2 core concepts.Use the ROS 1 bridge (optional)The ROS 1 bridge can connect topics from ROS 1 to ROS 2 and vice-versa. +See the dedicateddocumentationon how to build and use the ROS 1 bridge.Stay up to dateSeeMaintain source checkoutto periodically refresh your source installation.TroubleshootTroubleshooting techniques can be foundhere.UninstallIf you installed your workspace with colcon as instructed above, “uninstalling” could be just a matter of opening a new terminal and not sourcing the workspace’ssetupfile. +This way, your environment will behave as though there is no Jazzy install on your system.If you’re also trying to free up space, you can delete the entire workspace directory with:rm-rf~/ros2_jazzy + +Code Examples: + +Language: unknown +xcode-select--install# This command will not succeed if you have not installed Xcode.appsudoxcode-select--switch/Applications/Xcode.app/Contents/Developer# If you installed Xcode.app manually, you need to either open it or run:sudoxcodebuild-license# To accept the Xcode.app license + +Language: unknown +brewdoctor + +Language: unknown +brewinstallasioassimpbisonbulletcmakeconsole_bridgecppcheck\cuniteigenfreetypegraphvizopencvopensslorocos-kdlpcrepoco\pyqt@5pythonqt@5sipspdlogtinyxml2 + +Language: unknown +# Add the openssl dir for DDS-Security# if you are using BASH, then replace '.zshrc' with '.bashrc'echo"export OPENSSL_ROOT_DIR=$(brew--prefixopenssl)">>~/.zshrc# Add the Qt directory to the PATH and CMAKE_PREFIX_PATHexportCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH:$(brew--prefixqt@5)exportPATH=$PATH:$(brew--prefixqt@5)/bin + +Language: unknown +python3-mpipinstall--upgradepip + +python3-mpipinstall-U\--config-settings="--global-option=build_ext"\--config-settings="--global-option=-I$(brew--prefixgraphviz)/include/"\--config-settings="--global-option=-L$(brew--prefixgraphviz)/lib/"\argcompletecatkin_pkgcolcon-common-extensionscoverage\cryptographyempyflake8flake8-blind-except==0.1.1flake8-builtins\flake8-class-newlineflake8-comprehensionsflake8-deprecated\flake8-docstringsflake8-import-orderflake8-quotes\importlib-metadatajsonschemalark==1.1.1lxmlmatplotlibmockmypy==0.931netifaces\nosepep8psutilpydocstylepydotpygraphvizpyparsing==2.4.7\pytest-mockrosdeprosdistrosetuptools==59.6.0vcstool + +Language: unknown +rosinstall_generatorcatkincommon_msgsroscpprosmsg--rosdistrokinetic--deps--wet-only--tar>kinetic-ros2-bridge-deps.rosinstall +wstoolinit-j8srckinetic-ros2-bridge-deps.rosinstall + +Language: unknown +mkdir-p~/ros2_jazzy/srccd~/ros2_jazzy +vcsimport--inputhttps://raw.githubusercontent.com/ros2/ros2/jazzy/ros2.repossrc + +Language: unknown +cd~/ros2_jazzy/ +colconbuild--symlink-install--packages-skip-by-deppython_qt_binding + +Language: unknown +.~/ros2_jazzy/install/setup.zsh + +Language: unknown +ros2rundemo_nodes_cpptalker + +Language: unknown +ros2rundemo_nodes_pylistener + +Language: unknown +rm-rf~/ros2_jazzy diff --git a/extract.py b/extract.py new file mode 100644 index 0000000..8e468c2 --- /dev/null +++ b/extract.py @@ -0,0 +1,36 @@ +# extract_to_files.py +from pymongo import MongoClient +import os +import json +from typing import Dict, Any + +def export_mongodb_to_files(output_dir: str = "exported_docs"): + client = MongoClient('mongodb://localhost:27017/') + db = client['ros2_rag'] + collection = db['documentation'] + os.makedirs(output_dir, exist_ok=True) + for subdomain in collection.distinct('subdomain'): + subdomain_dir = os.path.join(output_dir, subdomain) + os.makedirs(subdomain_dir, exist_ok=True) + + for doc in collection.find({'subdomain': subdomain}): + filename = doc['content'].get('title', '').replace(' ', '_') + if not filename: + filename = doc['source']['url'].split('/')[-1] + + filepath = os.path.join(subdomain_dir, f"{filename}.txt") + + with open(filepath, 'w', encoding='utf-8') as f: + f.write(f"Title: {doc['content'].get('title', '')}\n") + f.write(f"URL: {doc['source']['url']}\n") + f.write(f"Section: {doc['metadata'].get('parent_section', '')}\n") + f.write("-" * 80 + "\n\n") + f.write(doc['content'].get('body', '')) + if doc['content'].get('code_snippets'): + f.write("\n\nCode Examples:\n") + for code in doc['content']['code_snippets']: + f.write(f"\nLanguage: {code['language']}\n") + f.write(code['code'] + "\n") + +if __name__ == "__main__": + export_mongodb_to_files() \ No newline at end of file diff --git a/gradio-app/README.md b/gradio-app/README.md new file mode 100644 index 0000000..2677305 --- /dev/null +++ b/gradio-app/README.md @@ -0,0 +1,11 @@ +--- +title: ROS2 Expert Assistant +emoji: 🤖 +colorFrom: blue +colorTo: purple +sdk: gradio +sdk_version: 4.19.2 +app_file: app.py +pinned: false +python_version: 3.10.13 +--- \ No newline at end of file diff --git a/gradio-app/app.py b/gradio-app/app.py new file mode 100644 index 0000000..b6f85ed --- /dev/null +++ b/gradio-app/app.py @@ -0,0 +1,227 @@ +import spaces +import os +import gradio as gr +import torch +from transformers import AutoTokenizer, TextStreamer, pipeline, AutoModelForCausalLM +from langchain_community.embeddings import HuggingFaceInstructEmbeddings +from langchain_community.vectorstores import Chroma +from langchain.prompts import PromptTemplate +from langchain.chains import RetrievalQA +from langchain_community.llms import HuggingFacePipeline + +# System prompts +DEFAULT_SYSTEM_PROMPT = """ +You are a ROS2 expert assistant. Based on the context provided, give direct and concise answers. +If the information is not in the context, respond with "I don't find that information in the available documentation." +Keep responses to 1-2 lines maximum. +""".strip() + +# Expanded pre-populated questions +PREDEFINED_QUESTIONS = [ + "Select a question...", + "Tell me how can I navigate to a specific pose - include replanning aspects in your answer.", + "Can you provide me with code for this task?", + "How do I set up obstacle avoidance in ROS2 navigation?", + "What are the key parameters for tuning the nav2 planner?", + "How do I integrate custom recovery behaviors?" +] + +def generate_prompt(context: str, question: str, system_prompt: str = DEFAULT_SYSTEM_PROMPT) -> str: + return f""" +[INST] <> +{system_prompt} +<> +Context: {context} +Question: {question} +Answer: [/INST] +""".strip() + +# Initialize embeddings and database +embeddings = HuggingFaceInstructEmbeddings( + model_name="hkunlp/instructor-base", + model_kwargs={"device": "cpu"} +) + +db = Chroma( + persist_directory="db", + embedding_function=embeddings +) + +def initialize_model(): + model_id = "meta-llama/Llama-3.2-3B-Instruct" + token = os.environ.get("HF_TOKEN") + + tokenizer = AutoTokenizer.from_pretrained(model_id, token=token) + model = AutoModelForCausalLM.from_pretrained( + model_id, + token=token, + device_map="cuda" if torch.cuda.is_available() else "cpu" + ) + + return model, tokenizer + +def question_selected(question): + if question == "Select a question...": + return "" + return question + +@spaces.GPU +def respond(message, history, system_message, max_tokens, temperature, top_p): + try: + # Initialize chat history if None + history = history or [] + + if not message.strip(): + history.append((message, "Please enter a question or select one from the dropdown menu.")) + return history + + model, tokenizer = initialize_model() + + # Get context from database + retriever = db.as_retriever(search_kwargs={"k": 2}) + docs = retriever.get_relevant_documents(message) + context = "\n".join([doc.page_content for doc in docs]) + + # Generate prompt + prompt = generate_prompt(context=context, question=message, system_prompt=system_message) + + # Set up the pipeline + text_pipeline = pipeline( + "text-generation", + model=model, + tokenizer=tokenizer, + max_new_tokens=max_tokens, + temperature=temperature, + top_p=top_p, + repetition_penalty=1.15 + ) + + # Generate response + output = text_pipeline( + prompt, + return_full_text=False, + max_new_tokens=max_tokens + )[0]['generated_text'] + + # Add the new exchange to history + history.append((message, output.strip())) + + return history + + except Exception as e: + history.append((message, f"An error occurred: {str(e)}")) + return history + +def clear_input(): + return gr.Textbox.update(value="") + +# Create the Gradio interface +with gr.Blocks(title="ROS2 Expert Assistant") as demo: + gr.Markdown("# ROS2 Expert Assistant") + gr.Markdown("Ask questions about ROS2, navigation, and robotics. I'll provide concise answers based on the available documentation.") + + with gr.Row(): + with gr.Column(scale=8): + # Dropdown for predefined questions + question_dropdown = gr.Dropdown( + choices=PREDEFINED_QUESTIONS, + value="Select a question...", + label="Pre-defined Questions" + ) + + with gr.Row(): + # Chat interface + chatbot = gr.Chatbot() + + with gr.Row(): + # Message input + msg = gr.Textbox( + label="Your Question", + placeholder="Type your question here or select one from the dropdown above...", + lines=2 + ) + + with gr.Row(): + submit = gr.Button("Submit") + clear = gr.Button("Clear") + + with gr.Accordion("Advanced Settings", open=False): + system_message = gr.Textbox( + value=DEFAULT_SYSTEM_PROMPT, + label="System Message", + lines=3 + ) + max_tokens = gr.Slider( + minimum=1, + maximum=2048, + value=500, + step=1, + label="Max new tokens" + ) + temperature = gr.Slider( + minimum=0.1, + maximum=4.0, + value=0.1, + step=0.1, + label="Temperature" + ) + top_p = gr.Slider( + minimum=0.1, + maximum=1.0, + value=0.95, + step=0.05, + label="Top-p" + ) + + # Add custom CSS for tooltip + gr.Markdown(""" + + """) + + # Event handlers + question_dropdown.change( + question_selected, + inputs=[question_dropdown], + outputs=[msg] + ) + + def submit_and_clear(message, history, system_message, max_tokens, temperature, top_p): + # First get the response + new_history = respond(message, history, system_message, max_tokens, temperature, top_p) + # Then clear the input + return new_history, gr.Textbox.update(value="") + + submit.click( + submit_and_clear, + inputs=[ + msg, + chatbot, + system_message, + max_tokens, + temperature, + top_p + ], + outputs=[chatbot, msg] + ) + + clear.click(lambda: (None, ""), None, [chatbot, msg], queue=False) + msg.submit( + submit_and_clear, + inputs=[ + msg, + chatbot, + system_message, + max_tokens, + temperature, + top_p + ], + outputs=[chatbot, msg] + ) + +if __name__ == "__main__": + demo.launch(share=True) \ No newline at end of file diff --git a/gradio-app/db/chroma.sqlite3 b/gradio-app/db/chroma.sqlite3 new file mode 100644 index 0000000..266ac10 --- /dev/null +++ b/gradio-app/db/chroma.sqlite3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1a91d81b35b03ba3f915614a1fe47e9d71a05ada306b796620f3ac5810af494 +size 49790976 diff --git a/gradio-app/requirements.txt b/gradio-app/requirements.txt new file mode 100644 index 0000000..9a74ed7 --- /dev/null +++ b/gradio-app/requirements.txt @@ -0,0 +1,10 @@ +torch==2.0.1 +transformers +accelerate +huggingface_hub==0.25.2 +langchain +chromadb +InstructorEmbedding +sentence-transformers==2.2.2 +gradio>=4.0.0 +langchain-community \ No newline at end of file diff --git a/mongo_test.py b/mongo_test.py index b502ba6..b371dff 100644 --- a/mongo_test.py +++ b/mongo_test.py @@ -1,24 +1,110 @@ from pymongo import MongoClient +from datetime import datetime +import uuid +from loguru import logger -# Connect to MongoDB server (assuming it's running on localhost and port 27017) -client = MongoClient("mongodb://localhost:27017/") +def test_mongodb_connection(): + """Test MongoDB connection and basic CRUD operations with our schema""" + MONGO_URI = "mongodb://localhost:27017/" + DB_NAME = "ros2_rag" + + try: + client = MongoClient(MONGO_URI) + logger.info("Successfully connected to MongoDB") + client.admin.command('ping') + logger.info("Successfully pinged MongoDB server") + db = client[DB_NAME] + docs_collection = db['documentation'] + test_doc = { + "id": str(uuid.uuid4()), + "type": "documentation", + "subdomain": "ros2", + "source": { + "url": "https://docs.ros.org/en/jazzy/Installation/test.html", + "version": "jazzy", + "last_updated": datetime.utcnow().isoformat() + }, + "content": { + "title": "Test Document", + "section_path": ["Installation", "Test"], + "body": "This is a test document for ROS2 documentation.", + "code_snippets": [ + { + "language": "bash", + "code": "ros2 run test_package test_node", + "context": "Test command" + } + ] + }, + "metadata": { + "crawl_timestamp": datetime.utcnow().isoformat(), + "parent_section": "Installation" + } + } + logger.info("Testing CRUD operations...") + result = docs_collection.insert_one(test_doc) + logger.info(f"Inserted test document with ID: {result.inserted_id}") + retrieved_doc = docs_collection.find_one({"id": test_doc["id"]}) + if retrieved_doc: + logger.info("Successfully retrieved test document") + logger.info(f"Document title: {retrieved_doc['content']['title']}") + logger.info(f"Document subdomain: {retrieved_doc['subdomain']}") + update_result = docs_collection.update_one( + {"id": test_doc["id"]}, + {"$set": {"content.title": "Updated Test Document"}} + ) + logger.info(f"Updated {update_result.modified_count} document") + delete_result = docs_collection.delete_one({"id": test_doc["id"]}) + logger.info(f"Deleted {delete_result.deleted_count} document") + logger.info("\nTesting collection operations...") + collections = db.list_collection_names() + logger.info(f"Available collections: {collections}") + logger.info("\nTesting indexes...") + docs_collection.create_index("source.url", unique=True) + indexes = docs_collection.list_indexes() + logger.info("Available indexes:") + for index in indexes: + logger.info(f"- {index['name']}: {index['key']}") + + client.close() + logger.success("All MongoDB tests completed successfully!") + return True + + except Exception as e: + logger.error(f"MongoDB test failed: {e}") + return False + + finally: + try: + client.close() + logger.info("MongoDB connection closed") + except: + pass -# Access a test database -db = client.test_database +def main(): + logger.info("Starting MongoDB connection test...") + success = test_mongodb_connection() + + if success: + logger.info(""" +MongoDB is properly configured and ready for the ETL pipeline! + +Verified: +✓ Connection to MongoDB container +✓ Database creation +✓ Collection operations +✓ Schema validation +✓ CRUD operations +✓ Index creation + """) + else: + logger.error(""" +MongoDB test failed! Please check: +1. Is the MongoDB container running? +2. Are the connection credentials correct? +3. Is the port mapping correct? +4. Is the network configuration correct? + """) -# Access a test collection within the test database -collection = db.test_collection - -# Insert a sample document -sample_document = {"name": "RAG Test", "description": "Testing MongoDB connection"} -collection.insert_one(sample_document) - -# Retrieve and print the document -retrieved_document = collection.find_one({"name": "RAG Test"}) -print("Retrieved Document:", retrieved_document) - -# Clean up (optional): delete the test document -collection.delete_one({"name": "RAG Test"}) - -# Close the connection -client.close() +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/notebooks/01_etl_pipeline.ipynb b/notebooks/01_etl_pipeline.ipynb index e69de29..9877e5f 100644 --- a/notebooks/01_etl_pipeline.ipynb +++ b/notebooks/01_etl_pipeline.ipynb @@ -0,0 +1,8512 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "env: CLEARML_WEB_HOST=https://app.clear.ml/\n", + "env: CLEARML_API_HOST=https://api.clear.ml\n", + "env: CLEARML_FILES_HOST=https://files.clear.ml\n", + "env: CLEARML_API_ACCESS_KEY=POD1HUHAIBRTPE9B34N1Y82UYPGXUF\n", + "env: CLEARML_API_SECRET_KEY=xa9QjVtLX7t6kc9HDPv7ZsiKw84FX3nPqjTtu0_FfkOn0tWMRjVm_PSJD0JK6t2mTNc\n" + ] + } + ], + "source": [ + "%env CLEARML_WEB_HOST=https://app.clear.ml/\n", + "%env CLEARML_API_HOST=https://api.clear.ml\n", + "%env CLEARML_FILES_HOST=https://files.clear.ml\n", + "%env CLEARML_API_ACCESS_KEY=POD1HUHAIBRTPE9B34N1Y82UYPGXUF\n", + "%env CLEARML_API_SECRET_KEY=xa9QjVtLX7t6kc9HDPv7ZsiKw84FX3nPqjTtu0_FfkOn0tWMRjVm_PSJD0JK6t2mTNc" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "from clearml import Task\n", + "\n", + "# Initialize the task\n", + "task = Task.init(project_name=\"RAG-ROS2\", task_name=\"ETL Pipeline\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected to MongoDB\n" + ] + } + ], + "source": [ + "import requests\n", + "from bs4 import BeautifulSoup\n", + "from urllib.parse import urljoin, urlparse\n", + "from pymongo import MongoClient\n", + "import time\n", + "\n", + "# MongoDB setup\n", + "MONGO_URI = 'mongodb://localhost:27017'\n", + "MONGO_DB_NAME = 'rag_ros2'\n", + "MONGO_COLLECTION = 'ros_distributions'\n", + "\n", + "# Connect to MongoDB\n", + "client = MongoClient(MONGO_URI)\n", + "db = client[MONGO_DB_NAME]\n", + "collection = db[MONGO_COLLECTION]\n", + "\n", + "print(\"Connected to MongoDB\")" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "base_url = \"https://docs.ros.org/\"" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "visited_urls = set()" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "def save_to_mongodb(url, content):\n", + " \"\"\"\n", + " Save scraped content to MongoDB.\n", + " \"\"\"\n", + " document = {\n", + " \"url\": url,\n", + " \"content\": content,\n", + " \"timestamp\": time.time()\n", + " }\n", + " result = collection.insert_one(document)\n", + " print(f\"Saved content from {url} to MongoDB with id {result.inserted_id}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "def scrape_page_dfs(url, depth=0, max_depth=5):\n", + " \"\"\"\n", + " Perform DFS scraping of the given URL.\n", + " \"\"\"\n", + " if depth > max_depth or url in visited_urls:\n", + " return\n", + "\n", + " # Add to visited URLs\n", + " visited_urls.add(url)\n", + "\n", + " try:\n", + " # Fetch the page content\n", + " response = requests.get(url, timeout=10)\n", + " if response.status_code != 200:\n", + " print(f\"Failed to access {url} (Status code: {response.status_code})\")\n", + " return\n", + "\n", + " print(f\"\\nScraping {url} (Depth: {depth})\")\n", + " soup = BeautifulSoup(response.content, \"html.parser\")\n", + "\n", + " # Prepare content for saving\n", + " content = {\n", + " \"title\": soup.title.string if soup.title else \"No title\",\n", + " \"text\": soup.get_text(),\n", + " \"headers\": [h.text for h in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])],\n", + " }\n", + "\n", + " # Save content to MongoDB\n", + " save_to_mongodb(url, content)\n", + "\n", + " # Extract internal links and perform DFS\n", + " links = soup.find_all('a', href=True)\n", + " for link in links:\n", + " href = link['href']\n", + " full_url = urljoin(url, href)\n", + " \n", + " # Ensure the link is within the docs.ros.org domain and not visited\n", + " if base_url in full_url and full_url not in visited_urls:\n", + " scrape_page_dfs(full_url, depth + 1, max_depth)\n", + "\n", + " except Exception as e:\n", + " print(f\"Error scraping {url}: {e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Scraping https://docs.ros.org/ (Depth: 0)\n", + "Saved content from https://docs.ros.org/ to MongoDB with id 674279e7b98d7a37c0432de3\n", + "\n", + "Scraping https://docs.ros.org/en/humble (Depth: 1)\n", + "Saved content from https://docs.ros.org/en/humble to MongoDB with id 674279e7b98d7a37c0432de4\n", + "Failed to access https://docs.ros.org/en/Installation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Ubuntu-Install-Debs.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Windows-Install-Binary.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/RHEL-Install-RPMs.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/Ubuntu-Development-Setup.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/Ubuntu-Install-Binary.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/Windows-Development-Setup.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/RHEL-Development-Setup.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/RHEL-Install-Binary.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/macOS-Development-Setup.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/Fedora-Development-Setup.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Alternatives/Latest-Development-Setup.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Maintaining-a-Source-Checkout.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/Testing.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/DDS-Implementations.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/DDS-Implementations/Install-Connext-Security-Plugins.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/DDS-Implementations/Install-Connext-University-Eval.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/DDS-Implementations/Working-with-Eclipse-CycloneDDS.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/DDS-Implementations/Working-with-GurumNetworks-GurumDDS.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Installation/DDS-Implementations/Working-with-eProsima-Fast-DDS.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Jazzy-Jalisco.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Jazzy-Jalisco-Complete-Changelog.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Iron-Irwini.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Iron-Irwini-Complete-Changelog.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Humble-Hawksbill.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Humble-Hawksbill-Complete-Changelog.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Rolling-Ridley.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Development.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Kilted-Kaiju.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/End-of-Life.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Galactic-Geochelone.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Galactic-Geochelone-Complete-Changelog.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Foxy-Fitzroy.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Eloquent-Elusor.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Dashing-Diademata.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Crystal-Clemmys.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Bouncy-Bolson.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Ardent-Apalone.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Beta3-Overview.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Beta2-Overview.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Beta1-Overview.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Alpha-Overview.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Releases/Release-Process.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Introducing-Turtlesim/Introducing-Turtlesim.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Nodes/Understanding-ROS2-Nodes.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Topics/Understanding-ROS2-Topics.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Services/Understanding-ROS2-Services.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Parameters/Understanding-ROS2-Parameters.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Actions/Understanding-ROS2-Actions.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Using-Rqt-Console/Using-Rqt-Console.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Launching-Multiple-Nodes/Launching-Multiple-Nodes.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-CLI-Tools/Recording-And-Playing-Back-Data/Recording-And-Playing-Back-Data.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Creating-A-Workspace/Creating-A-Workspace.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Creating-Your-First-ROS2-Package.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Service-And-Client.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Service-And-Client.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Custom-ROS2-Interfaces.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Single-Package-Define-And-Use-Interface.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-CPP.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Using-Parameters-In-A-Class-Python.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Getting-Started-With-Ros2doctor.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Beginner-Client-Libraries/Pluginlib.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Rosdep.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Creating-an-Action.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Writing-an-Action-Server-Client/Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Writing-an-Action-Server-Client/Py.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Writing-a-Composable-Node.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Composition.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Monitoring-For-Parameter-Changes-CPP.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Launch/Launch-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Launch/Creating-Launch-Files.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Launch/Launch-system.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Launch/Using-Substitutions.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Launch/Using-Event-Handlers.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Launch/Using-ROS2-Launch-For-Large-Projects.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Tf2-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Introduction-To-Tf2.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Py.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Py.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Listener-Py.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Listener-Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Adding-A-Frame-Py.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Adding-A-Frame-Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Learning-About-Tf2-And-Time-Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Time-Travel-With-Tf2-Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Debugging-Tf2-Problems.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Quaternion-Fundamentals.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Tf2/Using-Stamped-Datatypes-With-Tf2-Ros-MessageFilter.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Testing/Testing-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Testing/CLI.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Testing/Cpp.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Testing/Python.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/Testing/BuildFarmTesting.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/URDF-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/Building-a-Visual-Robot-Model-with-URDF-from-Scratch.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/Building-a-Movable-Robot-Model-with-URDF.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/Adding-Physical-and-Collision-Properties-to-a-URDF-Model.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/Using-Xacro-to-Clean-Up-a-URDF-File.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/Using-URDF-with-Robot-State-Publisher.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/URDF/Exporting-an-URDF-File.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/RViz/RViz-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/RViz/RViz-User-Guide/RViz-User-Guide.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/RViz/RViz-Custom-Display/RViz-Custom-Display.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Intermediate/RViz/Marker-Display-types/Marker-Display-types.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Topic-Statistics-Tutorial/Topic-Statistics-Tutorial.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Discovery-Server/Discovery-Server.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Allocator-Template-Tutorial.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/FastDDS-Configuration.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Recording-A-Bag-From-Your-Own-Node-CPP.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Recording-A-Bag-From-Your-Own-Node-Py.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/ROS2-Tracing-Trace-and-Analyze.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Reading-From-A-Bag-File-CPP.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Simulation-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Simulation-Webots.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Installation-Ubuntu.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Installation-Windows.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Installation-MacOS.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Basic.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Setting-Up-Simulation-Webots-Advanced.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Simulation-Supervisor.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Webots/Simulation-Reset-Handler.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Gazebo/Simulation-Gazebo.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Simulators/Gazebo/Gazebo.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/Security-Main.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/Introducing-ros2-security.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/The-Keystore.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/Security-on-Two.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/Examine-Traffic.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/Access-Controls.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Security/Deployment-Guidelines.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Quality-of-Service.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Managed-Nodes.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Intra-Process-Communication.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Rosbag-with-ROS1-Bridge.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Real-Time-Programming.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/dummy-robot-demo.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Logging-and-logger-configuration.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Content-Filtering-Subscription.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Miscellaneous.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Miscellaneous/Deploying-ROS-2-on-IBM-Cloud.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Miscellaneous/Eclipse-Oxygen-with-ROS-2-and-rviz2.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Miscellaneous/Building-Realtime-rt_preempt-kernel-for-ROS-2.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Miscellaneous/Building-ROS2-Package-with-eclipse-2021-06.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Installation-Troubleshooting.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Developing-a-ROS-2-Package.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Documenting-a-ROS-2-Package.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Ament-CMake-Documentation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Ament-CMake-Python-Documentation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Packages.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Package-XML.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Interfaces.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Package-Example.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Python-Package-Example.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Python-Packages.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Launch-Files.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Parameters.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Migrating-from-ROS1/Migrating-Scripts.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Launch-file-different-formats.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Launching-composable-nodes.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Node-arguments.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Sync-Vs-Async.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/DDS-tuning.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Overriding-QoS-Policies-For-Recording-And-Playback.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Working-with-multiple-RMW-implementations.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Cross-compilation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Releasing/Releasing-a-Package.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Releasing/Index-Your-Packages.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Releasing/First-Time-Release.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Releasing/Subsequent-Releases.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Releasing/Release-Team-Repository.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Releasing/Release-Track.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Using-Python-Packages.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Run-2-nodes-in-single-or-separate-docker-containers.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Visualizing-ROS-2-Data-With-Foxglove-Studio.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Core-maintainer-guide.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Building-a-Custom-Deb-Package.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Building-ROS-2-with-Tracing-Instrumentation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Topics-Services-Actions.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Using-Variants.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Using-ros2-param.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Using-ros1_bridge-Jammy-upstream.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Configure-ZeroCopy-loaned-messages.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Installing-on-Raspberry-Pi.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Using-callback-groups.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Getting-Backtraces-in-ROS-2.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/ROS-2-IDEs.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Setup-ROS-2-with-VSCode-and-Docker-Container.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Using-Custom-Rosdistro.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Nodes.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Discovery.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Interfaces.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Topics.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Services.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Actions.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Parameters.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Command-Line-Tools.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Launch.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Basic/About-Client-Libraries.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Domain-ID.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Different-Middleware-Vendors.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Logging.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Quality-of-Service-Settings.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Executors.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Topic-Statistics.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-RQt.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Composition.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Cross-Compilation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Security.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Intermediate/About-Tf2.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Advanced.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Advanced/About-Build-System.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Advanced/About-Internal-Interfaces.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Concepts/Advanced/About-Middleware-Implementations.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Contact.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing/Developer-Guide.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing/Code-Style-Language-Versions.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing/Quality-Guide.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing/Build-Farms.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing/Windows-Tips-and-Tricks.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Contributing/Contributing-To-ROS-2-Documentation.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Features.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Feature-Ideas.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Roadmap.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/ROSCon-Content.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Governance.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Marketing.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/The-ROS2-Project/Metrics.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Package-Docs.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Related-Projects.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Related-Projects/Intel-ROS2-Projects.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Related-Projects/Nvidia-ROS2-Projects.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Glossary.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Citations.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/jazzy/index.html (Status code: 404)\n", + "\n", + "Scraping https://docs.ros.org/en/humble#ros-2-documentation (Depth: 2)\n", + "Saved content from https://docs.ros.org/en/humble#ros-2-documentation to MongoDB with id 67427a55b98d7a37c0432de5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ (Depth: 3)\n", + "Saved content from https://docs.ros.org/en/humble/p/ to MongoDB with id 67427a5cb98d7a37c0432de6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/?C=N;O=D (Depth: 4)\n", + "Saved content from https://docs.ros.org/en/humble/p/?C=N;O=D to MongoDB with id 67427a5db98d7a37c0432de7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/?C=N;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/?C=N;O=A to MongoDB with id 67427a5eb98d7a37c0432de8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/?C=M;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/?C=M;O=A to MongoDB with id 67427a60b98d7a37c0432de9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/?C=S;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/?C=S;O=A to MongoDB with id 67427a61b98d7a37c0432dea\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/?C=D;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/?C=D;O=A to MongoDB with id 67427a62b98d7a37c0432deb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/ to MongoDB with id 67427a62b98d7a37c0432dec\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/zstd_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/zstd_vendor/ to MongoDB with id 67427a63b98d7a37c0432ded\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/zstd_point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/zstd_point_cloud_transport/ to MongoDB with id 67427a63b98d7a37c0432dee\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/zlib_point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/zlib_point_cloud_transport/ to MongoDB with id 67427a64b98d7a37c0432def\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/zbar_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/zbar_ros/ to MongoDB with id 67427a64b98d7a37c0432df0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/xacro/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/xacro/ to MongoDB with id 67427a65b98d7a37c0432df1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/wireless_watcher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/wireless_watcher/ to MongoDB with id 67427a65b98d7a37c0432df2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/wiimote/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/wiimote/ to MongoDB with id 67427a66b98d7a37c0432df3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/whill_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/whill_msgs/ to MongoDB with id 67427a66b98d7a37c0432df4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/whill_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/whill_examples/ to MongoDB with id 67427a66b98d7a37c0432df5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/whill_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/whill_driver/ to MongoDB with id 67427a67b98d7a37c0432df6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/whill_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/whill_description/ to MongoDB with id 67427a67b98d7a37c0432df7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/whill_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/whill_bringup/ to MongoDB with id 67427a68b98d7a37c0432df8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/whill/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/whill/ to MongoDB with id 67427a68b98d7a37c0432df9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_universal_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_universal_robot/ to MongoDB with id 67427a69b98d7a37c0432dfa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_turtlebot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_turtlebot/ to MongoDB with id 67427a69b98d7a37c0432dfb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_tiago/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_tiago/ to MongoDB with id 67427a6ab98d7a37c0432dfc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_tests/ to MongoDB with id 67427a6ab98d7a37c0432dfd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_tesla/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_tesla/ to MongoDB with id 67427a6ab98d7a37c0432dfe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_msgs/ to MongoDB with id 67427a6bb98d7a37c0432dff\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_mavic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_mavic/ to MongoDB with id 67427a6bb98d7a37c0432e00\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_importer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_importer/ to MongoDB with id 67427a6cb98d7a37c0432e01\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_epuck/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_epuck/ to MongoDB with id 67427a6cb98d7a37c0432e02\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_driver/ to MongoDB with id 67427a6db98d7a37c0432e03\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2_control/ to MongoDB with id 67427a6db98d7a37c0432e04\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/webots_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/webots_ros2/ to MongoDB with id 67427a6eb98d7a37c0432e05\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/web_video_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/web_video_server/ to MongoDB with id 67427a6eb98d7a37c0432e06\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/warehouse_ros_sqlite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/warehouse_ros_sqlite/ to MongoDB with id 67427a6fb98d7a37c0432e07\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/warehouse_ros_mongo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/warehouse_ros_mongo/ to MongoDB with id 67427a6fb98d7a37c0432e08\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/warehouse_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/warehouse_ros/ to MongoDB with id 67427a70b98d7a37c0432e09\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vrpn_mocap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vrpn_mocap/ to MongoDB with id 67427a70b98d7a37c0432e0a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vmbc_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vmbc_interface/ to MongoDB with id 67427a71b98d7a37c0432e0b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vizanti_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vizanti_server/ to MongoDB with id 67427a71b98d7a37c0432e0c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vizanti_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vizanti_msgs/ to MongoDB with id 67427a72b98d7a37c0432e0d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vizanti_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vizanti_demos/ to MongoDB with id 67427a72b98d7a37c0432e0e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vizanti_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vizanti_cpp/ to MongoDB with id 67427a73b98d7a37c0432e0f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vizanti/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vizanti/ to MongoDB with id 67427a73b98d7a37c0432e10\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vitis_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vitis_common/ to MongoDB with id 67427a75b98d7a37c0432e11\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/visualization_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/visualization_msgs/ to MongoDB with id 67427a75b98d7a37c0432e12\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vision_msgs_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vision_msgs_rviz_plugins/ to MongoDB with id 67427a76b98d7a37c0432e13\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vision_msgs_layers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vision_msgs_layers/ to MongoDB with id 67427a77b98d7a37c0432e14\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vision_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vision_msgs/ to MongoDB with id 67427a77b98d7a37c0432e15\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vimbax_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vimbax_camera_msgs/ to MongoDB with id 67427a78b98d7a37c0432e16\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vimbax_camera_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vimbax_camera_examples/ to MongoDB with id 67427a78b98d7a37c0432e17\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vimbax_camera_events/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vimbax_camera_events/ to MongoDB with id 67427a79b98d7a37c0432e18\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vimbax_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vimbax_camera/ to MongoDB with id 67427a79b98d7a37c0432e19\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velodyne_pointcloud/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velodyne_pointcloud/ to MongoDB with id 67427a7ab98d7a37c0432e1a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velodyne_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velodyne_msgs/ to MongoDB with id 67427a7ab98d7a37c0432e1b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velodyne_laserscan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velodyne_laserscan/ to MongoDB with id 67427a7ab98d7a37c0432e1c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velodyne_gazebo_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velodyne_gazebo_plugins/ to MongoDB with id 67427a7bb98d7a37c0432e1d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velodyne_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velodyne_driver/ to MongoDB with id 67427a7cb98d7a37c0432e1e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velodyne/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velodyne/ to MongoDB with id 67427a7cb98d7a37c0432e1f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/velocity_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/velocity_controllers/ to MongoDB with id 67427a7db98d7a37c0432e20\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/vector_pursuit_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/vector_pursuit_controller/ to MongoDB with id 67427a7db98d7a37c0432e21\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/v4l2_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/v4l2_camera/ to MongoDB with id 67427a7eb98d7a37c0432e22\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/usb_cam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/usb_cam/ to MongoDB with id 67427a7eb98d7a37c0432e23\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/urdfdom_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/urdfdom_py/ to MongoDB with id 67427a7fb98d7a37c0432e24\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/urdf_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/urdf_test/ to MongoDB with id 67427a80b98d7a37c0432e25\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/urdf_parser_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/urdf_parser_plugin/ to MongoDB with id 67427a80b98d7a37c0432e26\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/urdf_launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/urdf_launch/ to MongoDB with id 67427a80b98d7a37c0432e27\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/urdf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/urdf/ to MongoDB with id 67427a81b98d7a37c0432e28\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_robot_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_robot_driver/ to MongoDB with id 67427a82b98d7a37c0432e29\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_msgs/ to MongoDB with id 67427a82b98d7a37c0432e2a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_moveit_config/ to MongoDB with id 67427a82b98d7a37c0432e2b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_description/ to MongoDB with id 67427a83b98d7a37c0432e2c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_dashboard_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_dashboard_msgs/ to MongoDB with id 67427a83b98d7a37c0432e2d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_controllers/ to MongoDB with id 67427a84b98d7a37c0432e2e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_client_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_client_library/ to MongoDB with id 67427a85b98d7a37c0432e2f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_calibration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_calibration/ to MongoDB with id 67427a85b98d7a37c0432e30\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur_bringup/ to MongoDB with id 67427a86b98d7a37c0432e31\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ur/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ur/ to MongoDB with id 67427a86b98d7a37c0432e32\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/unitree_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/unitree_ros/ to MongoDB with id 67427a87b98d7a37c0432e33\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/undo_path_global_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/undo_path_global_planner/ to MongoDB with id 67427a87b98d7a37c0432e34\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/udp_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/udp_msgs/ to MongoDB with id 67427a88b98d7a37c0432e35\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/udp_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/udp_driver/ to MongoDB with id 67427a88b98d7a37c0432e36\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_ubx_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_ubx_msgs/ to MongoDB with id 67427a89b98d7a37c0432e37\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_ubx_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_ubx_interfaces/ to MongoDB with id 67427a89b98d7a37c0432e38\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_serialization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_serialization/ to MongoDB with id 67427a8ab98d7a37c0432e39\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_nav_sat_fix_hp_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_nav_sat_fix_hp_node/ to MongoDB with id 67427a8bb98d7a37c0432e3a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_msgs/ to MongoDB with id 67427a8bb98d7a37c0432e3b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_gps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_gps/ to MongoDB with id 67427a8cb98d7a37c0432e3c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_dgnss_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_dgnss_node/ to MongoDB with id 67427a8db98d7a37c0432e3d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ublox_dgnss/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ublox_dgnss/ to MongoDB with id 67427a8db98d7a37c0432e3e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/twist_stamper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/twist_stamper/ to MongoDB with id 67427a8eb98d7a37c0432e3f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/twist_mux/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/twist_mux/ to MongoDB with id 67427a8eb98d7a37c0432e40\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tvm_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tvm_vendor/ to MongoDB with id 67427a8fb98d7a37c0432e41\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_std_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_std_msgs/ to MongoDB with id 67427a8fb98d7a37c0432e42\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_object_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_object_msgs/ to MongoDB with id 67427a90b98d7a37c0432e43\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_object_map_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_object_map_msgs/ to MongoDB with id 67427a90b98d7a37c0432e44\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_nav_msgs/ to MongoDB with id 67427a91b98d7a37c0432e45\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_multi_robot_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_multi_robot_msgs/ to MongoDB with id 67427a91b98d7a37c0432e46\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_msgs/ to MongoDB with id 67427a91b98d7a37c0432e47\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_graph_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_graph_msgs/ to MongoDB with id 67427a92b98d7a37c0432e48\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_geometry_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_geometry_msgs/ to MongoDB with id 67427a93b98d7a37c0432e49\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_geometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_geometry/ to MongoDB with id 67427a93b98d7a37c0432e4a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_geo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_geo_msgs/ to MongoDB with id 67427a93b98d7a37c0432e4b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tuw_airskin_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tuw_airskin_msgs/ to MongoDB with id 67427a94b98d7a37c0432e4c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlesim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlesim/ to MongoDB with id 67427a94b98d7a37c0432e4d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_tests/ to MongoDB with id 67427a95b98d7a37c0432e4e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_simulator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_simulator/ to MongoDB with id 67427a95b98d7a37c0432e4f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_setup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_setup/ to MongoDB with id 67427a96b98d7a37c0432e50\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_robot/ to MongoDB with id 67427a96b98d7a37c0432e51\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_python_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_python_tutorials/ to MongoDB with id 67427a96b98d7a37c0432e52\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_openai_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_openai_tutorials/ to MongoDB with id 67427a97b98d7a37c0432e53\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_node/ to MongoDB with id 67427a97b98d7a37c0432e54\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_navigation/ to MongoDB with id 67427a98b98d7a37c0432e55\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_msgs/ to MongoDB with id 67427a98b98d7a37c0432e56\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_ignition_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_ignition_toolbox/ to MongoDB with id 67427a99b98d7a37c0432e57\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_ignition_gui_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_ignition_gui_plugins/ to MongoDB with id 67427a99b98d7a37c0432e58\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_ignition_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_ignition_bringup/ to MongoDB with id 67427a9ab98d7a37c0432e59\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_diagnostics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_diagnostics/ to MongoDB with id 67427a9ab98d7a37c0432e5a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_description/ to MongoDB with id 67427a9bb98d7a37c0432e5b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_bringup/ to MongoDB with id 67427a9bb98d7a37c0432e5c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot4_base/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot4_base/ to MongoDB with id 67427a9cb98d7a37c0432e5d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot3_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot3_node/ to MongoDB with id 67427a9db98d7a37c0432e5e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot3_manipulation_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot3_manipulation_teleop/ to MongoDB with id 67427a9db98d7a37c0432e5f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot3_manipulation_hardware/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot3_manipulation_hardware/ to MongoDB with id 67427a9eb98d7a37c0432e60\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot3_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot3_gazebo/ to MongoDB with id 67427a9eb98d7a37c0432e61\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtlebot3_fake_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtlebot3_fake_node/ to MongoDB with id 67427a9fb98d7a37c0432e62\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtle_tf2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtle_tf2_py/ to MongoDB with id 67427a9fb98d7a37c0432e63\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtle_tf2_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtle_tf2_cpp/ to MongoDB with id 67427aa0b98d7a37c0432e64\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turtle_nest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turtle_nest/ to MongoDB with id 67427aa0b98d7a37c0432e65\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/turbojpeg_compressed_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/turbojpeg_compressed_image_transport/ to MongoDB with id 67427aa1b98d7a37c0432e66\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tricycle_steering_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tricycle_steering_controller/ to MongoDB with id 67427aa1b98d7a37c0432e67\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tricycle_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tricycle_controller/ to MongoDB with id 67427aa2b98d7a37c0432e68\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/transmission_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/transmission_interface/ to MongoDB with id 67427aa2b98d7a37c0432e69\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/trajectory_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/trajectory_msgs/ to MongoDB with id 67427aa3b98d7a37c0432e6a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tracetools_image_pipeline/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tracetools_image_pipeline/ to MongoDB with id 67427aa3b98d7a37c0432e6b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tracetools_analysis/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tracetools_analysis/ to MongoDB with id 67427aa4b98d7a37c0432e6c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tracetools_acceleration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tracetools_acceleration/ to MongoDB with id 67427aa5b98d7a37c0432e6d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tracetools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tracetools/ to MongoDB with id 67427aa5b98d7a37c0432e6e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/topic_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/topic_tools/ to MongoDB with id 67427aa6b98d7a37c0432e6f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/topic_statistics_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/topic_statistics_demo/ to MongoDB with id 67427aa6b98d7a37c0432e70\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/topic_monitor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/topic_monitor/ to MongoDB with id 67427aa7b98d7a37c0432e71\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tlsf_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tlsf_cpp/ to MongoDB with id 67427aa7b98d7a37c0432e72\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tlsf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tlsf/ to MongoDB with id 67427aa8b98d7a37c0432e73\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tile_map/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tile_map/ to MongoDB with id 67427aa9b98d7a37c0432e74\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_simulation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_simulation/ to MongoDB with id 67427aa9b98d7a37c0432e75\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_robot/ to MongoDB with id 67427aaab98d7a37c0432e76\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_rgbd_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_rgbd_sensors/ to MongoDB with id 67427aaab98d7a37c0432e77\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_navigation/ to MongoDB with id 67427aabb98d7a37c0432e78\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_moveit_config/ to MongoDB with id 67427aabb98d7a37c0432e79\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_laser_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_laser_sensors/ to MongoDB with id 67427aacb98d7a37c0432e7a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_gazebo/ to MongoDB with id 67427aacb98d7a37c0432e7b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_description/ to MongoDB with id 67427aadb98d7a37c0432e7c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_controller_configuration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_controller_configuration/ to MongoDB with id 67427aadb98d7a37c0432e7d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_bringup/ to MongoDB with id 67427aaeb98d7a37c0432e7e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tiago_2dnav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tiago_2dnav/ to MongoDB with id 67427aaeb98d7a37c0432e7f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/theora_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/theora_image_transport/ to MongoDB with id 67427aafb98d7a37c0432e80\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf_transformations/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf_transformations/ to MongoDB with id 67427aafb98d7a37c0432e81\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf_to_pose_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf_to_pose_publisher/ to MongoDB with id 67427ab0b98d7a37c0432e82\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_tools/ to MongoDB with id 67427ab0b98d7a37c0432e83\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_sensor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_sensor_msgs/ to MongoDB with id 67427ab1b98d7a37c0432e84\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_ros_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_ros_py/ to MongoDB with id 67427ab2b98d7a37c0432e85\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_ros/ to MongoDB with id 67427ab2b98d7a37c0432e86\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_py/ to MongoDB with id 67427ab3b98d7a37c0432e87\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_msgs/ to MongoDB with id 67427ab3b98d7a37c0432e88\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_kdl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_kdl/ to MongoDB with id 67427ab4b98d7a37c0432e89\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_geometry_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_geometry_msgs/ to MongoDB with id 67427ab4b98d7a37c0432e8a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_eigen_kdl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_eigen_kdl/ to MongoDB with id 67427ab5b98d7a37c0432e8b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_eigen/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_eigen/ to MongoDB with id 67427ab6b98d7a37c0432e8c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2_bullet/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2_bullet/ to MongoDB with id 67427ab6b98d7a37c0432e8d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tf2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tf2/ to MongoDB with id 67427ab7b98d7a37c0432e8e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_tf2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_tf2/ to MongoDB with id 67427ab7b98d7a37c0432e8f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_ros_gz_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_ros_gz_bridge/ to MongoDB with id 67427ab8b98d7a37c0432e90\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_rmw_implementation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_rmw_implementation/ to MongoDB with id 67427ab8b98d7a37c0432e91\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_msgs/ to MongoDB with id 67427ab9b98d7a37c0432e92\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_launch_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_launch_testing/ to MongoDB with id 67427ab9b98d7a37c0432e93\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_launch_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_launch_ros/ to MongoDB with id 67427abab98d7a37c0432e94\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/test_bond/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/test_bond/ to MongoDB with id 67427abab98d7a37c0432e95\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/teleop_twist_joy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/teleop_twist_joy/ to MongoDB with id 67427abbb98d7a37c0432e96\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/teleop_tools_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/teleop_tools_msgs/ to MongoDB with id 67427abbb98d7a37c0432e97\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/teleop_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/teleop_tools/ to MongoDB with id 67427abcb98d7a37c0432e98\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/tb4_sim_scenario/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/tb4_sim_scenario/ to MongoDB with id 67427abcb98d7a37c0432e99\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/system_modes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/system_modes/ to MongoDB with id 67427abdb98d7a37c0432e9a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sync_parameter_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sync_parameter_server/ to MongoDB with id 67427abdb98d7a37c0432e9b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_transform_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_transform_util/ to MongoDB with id 67427abfb98d7a37c0432e9c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_system_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_system_util/ to MongoDB with id 67427ac1b98d7a37c0432e9d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_serial_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_serial_util/ to MongoDB with id 67427ac2b98d7a37c0432e9e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_route_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_route_util/ to MongoDB with id 67427ac2b98d7a37c0432e9f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_roscpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_roscpp/ to MongoDB with id 67427ac3b98d7a37c0432ea0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_opencv_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_opencv_util/ to MongoDB with id 67427ac3b98d7a37c0432ea1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_math_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_math_util/ to MongoDB with id 67427ac4b98d7a37c0432ea2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_image_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_image_util/ to MongoDB with id 67427ac4b98d7a37c0432ea3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_geometry_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_geometry_util/ to MongoDB with id 67427ac5b98d7a37c0432ea4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_dbw_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_dbw_interface/ to MongoDB with id 67427ac6b98d7a37c0432ea5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_console_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_console_util/ to MongoDB with id 67427ac6b98d7a37c0432ea6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_console/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_console/ to MongoDB with id 67427ac7b98d7a37c0432ea7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/swri_cli_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/swri_cli_tools/ to MongoDB with id 67427ac7b98d7a37c0432ea8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/stomp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/stomp/ to MongoDB with id 67427ac8b98d7a37c0432ea9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/stereo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/stereo_msgs/ to MongoDB with id 67427ac9b98d7a37c0432eaa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/stereo_image_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/stereo_image_proc/ to MongoDB with id 67427ac9b98d7a37c0432eab\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/steering_controllers_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/steering_controllers_library/ to MongoDB with id 67427ac9b98d7a37c0432eac\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/std_srvs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/std_srvs/ to MongoDB with id 67427acab98d7a37c0432ead\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/std_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/std_msgs/ to MongoDB with id 67427acab98d7a37c0432eae\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/stcamera_grabber/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/stcamera_grabber/ to MongoDB with id 67427acbb98d7a37c0432eaf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/stcamera_components/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/stcamera_components/ to MongoDB with id 67427accb98d7a37c0432eb0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sros2_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sros2_cmake/ to MongoDB with id 67427accb98d7a37c0432eb1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sros2/ to MongoDB with id 67427accb98d7a37c0432eb2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/srdfdom/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/srdfdom/ to MongoDB with id 67427acdb98d7a37c0432eb3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sr_event_countdown/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sr_event_countdown/ to MongoDB with id 67427acdb98d7a37c0432eb4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sr_conditional/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sr_conditional/ to MongoDB with id 67427aceb98d7a37c0432eb5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sr_all_events_go/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sr_all_events_go/ to MongoDB with id 67427aceb98d7a37c0432eb6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sqlite3_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sqlite3_vendor/ to MongoDB with id 67427acfb98d7a37c0432eb7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/splsm_8_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/splsm_8_conversion/ to MongoDB with id 67427acfb98d7a37c0432eb8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/splsm_7_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/splsm_7_conversion/ to MongoDB with id 67427ad0b98d7a37c0432eb9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/spinnaker_synchronized_camera_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/spinnaker_synchronized_camera_driver/ to MongoDB with id 67427ad0b98d7a37c0432eba\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/spinnaker_camera_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/spinnaker_camera_driver/ to MongoDB with id 67427ad1b98d7a37c0432ebb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/spatio_temporal_voxel_layer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/spatio_temporal_voxel_layer/ to MongoDB with id 67427ad1b98d7a37c0432ebc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/spacenav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/spacenav/ to MongoDB with id 67427ad2b98d7a37c0432ebd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/social_nav_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/social_nav_util/ to MongoDB with id 67427ad2b98d7a37c0432ebe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/social_nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/social_nav_msgs/ to MongoDB with id 67427ad2b98d7a37c0432ebf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/social_nav_metrics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/social_nav_metrics/ to MongoDB with id 67427ad3b98d7a37c0432ec0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/soar_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/soar_ros/ to MongoDB with id 67427ad4b98d7a37c0432ec1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/snowbot_operating_system/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/snowbot_operating_system/ to MongoDB with id 67427ad4b98d7a37c0432ec2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/smclib/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/smclib/ to MongoDB with id 67427ad5b98d7a37c0432ec3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/smach_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/smach_ros/ to MongoDB with id 67427ad5b98d7a37c0432ec4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/smach_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/smach_msgs/ to MongoDB with id 67427ad6b98d7a37c0432ec5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/smach/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/smach/ to MongoDB with id 67427ad6b98d7a37c0432ec6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/smacc2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/smacc2_msgs/ to MongoDB with id 67427ad6b98d7a37c0432ec7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/smacc2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/smacc2/ to MongoDB with id 67427ad7b98d7a37c0432ec8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_three_some/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_three_some/ to MongoDB with id 67427ad8b98d7a37c0432ec9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_test_moveit_ur5_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_test_moveit_ur5_sim/ to MongoDB with id 67427ad8b98d7a37c0432eca\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_simple_action_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_simple_action_client/ to MongoDB with id 67427ad9b98d7a37c0432ecb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_respira_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_respira_1/ to MongoDB with id 67427adab98d7a37c0432ecc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_pubsub_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_pubsub_1/ to MongoDB with id 67427adab98d7a37c0432ecd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_panda_moveit2z_cb_inventory/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_panda_moveit2z_cb_inventory/ to MongoDB with id 67427adbb98d7a37c0432ece\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_pack_ml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_pack_ml/ to MongoDB with id 67427adcb98d7a37c0432ecf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_multi_stage_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_multi_stage_1/ to MongoDB with id 67427addb98d7a37c0432ed0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_multi_panda_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_multi_panda_sim/ to MongoDB with id 67427addb98d7a37c0432ed1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_husky_barrel_search_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_husky_barrel_search_1/ to MongoDB with id 67427adeb98d7a37c0432ed2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dancebot_ue/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dancebot_ue/ to MongoDB with id 67427adfb98d7a37c0432ed3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dancebot_office_ue/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dancebot_office_ue/ to MongoDB with id 67427adfb98d7a37c0432ed4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dancebot_mine_ue/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dancebot_mine_ue/ to MongoDB with id 67427ae0b98d7a37c0432ed5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dancebot_artgallery_ue/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dancebot_artgallery_ue/ to MongoDB with id 67427ae0b98d7a37c0432ed6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse_4/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse_4/ to MongoDB with id 67427ae1b98d7a37c0432ed7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse_3/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse_3/ to MongoDB with id 67427ae2b98d7a37c0432ed8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse_2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse_2/ to MongoDB with id 67427ae2b98d7a37c0432ed9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dance_bot_warehouse/ to MongoDB with id 67427ae3b98d7a37c0432eda\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dance_bot_strikes_back/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dance_bot_strikes_back/ to MongoDB with id 67427ae4b98d7a37c0432edb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_dance_bot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_dance_bot/ to MongoDB with id 67427ae5b98d7a37c0432edc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_coretest_transition_speed_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_coretest_transition_speed_1/ to MongoDB with id 67427ae5b98d7a37c0432edd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_branching/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_branching/ to MongoDB with id 67427ae6b98d7a37c0432ede\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_aws_warehouse_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_aws_warehouse_navigation/ to MongoDB with id 67427ae6b98d7a37c0432edf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_autoware_avp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_autoware_avp/ to MongoDB with id 67427ae7b98d7a37c0432ee0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_subscribers_performance_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_subscribers_performance_test/ to MongoDB with id 67427ae8b98d7a37c0432ee1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_services/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_services/ to MongoDB with id 67427ae8b98d7a37c0432ee2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_performance_trace_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_performance_trace_1/ to MongoDB with id 67427ae9b98d7a37c0432ee3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_openai/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_openai/ to MongoDB with id 67427ae9b98d7a37c0432ee4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_mode_states/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_mode_states/ to MongoDB with id 67427aeab98d7a37c0432ee5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_lifecycle/ to MongoDB with id 67427aeab98d7a37c0432ee6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_http/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_http/ to MongoDB with id 67427aebb98d7a37c0432ee7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_hierarchy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_hierarchy/ to MongoDB with id 67427aecb98d7a37c0432ee8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic_24hr/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic_24hr/ to MongoDB with id 67427aecb98d7a37c0432ee9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_atomic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_atomic/ to MongoDB with id 67427aedb98d7a37c0432eea\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sm_advanced_recovery_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sm_advanced_recovery_1/ to MongoDB with id 67427aedb98d7a37c0432eeb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/slider_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/slider_publisher/ to MongoDB with id 67427aeeb98d7a37c0432eec\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/slg_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/slg_msgs/ to MongoDB with id 67427aeeb98d7a37c0432eed\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/slam_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/slam_toolbox/ to MongoDB with id 67427aefb98d7a37c0432eee\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/simple_grasping/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/simple_grasping/ to MongoDB with id 67427aefb98d7a37c0432eef\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/simple_actions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/simple_actions/ to MongoDB with id 67427af1b98d7a37c0432ef0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sicks300_2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sicks300_2/ to MongoDB with id 67427af1b98d7a37c0432ef1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sick_scan_xd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sick_scan_xd/ to MongoDB with id 67427af3b98d7a37c0432ef2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sick_safevisionary_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sick_safevisionary_tests/ to MongoDB with id 67427af3b98d7a37c0432ef3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sick_safetyscanners_base/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sick_safetyscanners_base/ to MongoDB with id 67427af4b98d7a37c0432ef4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sick_safetyscanners2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sick_safetyscanners2/ to MongoDB with id 67427af5b98d7a37c0432ef5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/shared_queues_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/shared_queues_vendor/ to MongoDB with id 67427af6b98d7a37c0432ef6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/shape_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/shape_msgs/ to MongoDB with id 67427af6b98d7a37c0432ef7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/serial_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/serial_driver/ to MongoDB with id 67427af6b98d7a37c0432ef8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/septentrio_gnss_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/septentrio_gnss_driver/ to MongoDB with id 67427af8b98d7a37c0432ef9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sensor_msgs_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sensor_msgs_py/ to MongoDB with id 67427af8b98d7a37c0432efa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sensor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sensor_msgs/ to MongoDB with id 67427af9b98d7a37c0432efb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/self_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/self_test/ to MongoDB with id 67427af9b98d7a37c0432efc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sdformat_urdf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sdformat_urdf/ to MongoDB with id 67427afab98d7a37c0432efd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sdc21x0/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sdc21x0/ to MongoDB with id 67427afab98d7a37c0432efe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/schunk_svh_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/schunk_svh_tests/ to MongoDB with id 67427afbb98d7a37c0432eff\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/schunk_svh_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/schunk_svh_library/ to MongoDB with id 67427afbb98d7a37c0432f00\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/schunk_svh_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/schunk_svh_driver/ to MongoDB with id 67427afcb98d7a37c0432f01\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_status/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_status/ to MongoDB with id 67427afcb98d7a37c0432f02\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_x11/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_x11/ to MongoDB with id 67427afdb98d7a37c0432f03\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_test/ to MongoDB with id 67427afdb98d7a37c0432f04\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_rviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_rviz/ to MongoDB with id 67427afeb98d7a37c0432f05\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_ros_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_ros_test/ to MongoDB with id 67427afeb98d7a37c0432f06\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_ros/ to MongoDB with id 67427afeb98d7a37c0432f07\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_pybullet/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_pybullet/ to MongoDB with id 67427affb98d7a37c0432f08\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_py_trees_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_py_trees_ros/ to MongoDB with id 67427affb98d7a37c0432f09\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_os/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_os/ to MongoDB with id 67427b00b98d7a37c0432f0a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_nav2_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_nav2_test/ to MongoDB with id 67427b00b98d7a37c0432f0b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_nav2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_nav2/ to MongoDB with id 67427b00b98d7a37c0432f0c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_moveit2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_moveit2/ to MongoDB with id 67427b01b98d7a37c0432f0d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_kubernetes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_kubernetes/ to MongoDB with id 67427b02b98d7a37c0432f0e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_interfaces/ to MongoDB with id 67427b02b98d7a37c0432f0f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_gazebo_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_gazebo_test/ to MongoDB with id 67427b02b98d7a37c0432f10\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_gazebo/ to MongoDB with id 67427b03b98d7a37c0432f11\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_floorplan_dsl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_floorplan_dsl/ to MongoDB with id 67427b03b98d7a37c0432f12\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_docker_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_docker_test/ to MongoDB with id 67427b04b98d7a37c0432f13\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_docker/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_docker/ to MongoDB with id 67427b04b98d7a37c0432f14\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_coverage/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_coverage/ to MongoDB with id 67427b05b98d7a37c0432f15\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution_control/ to MongoDB with id 67427b05b98d7a37c0432f16\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_execution/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_execution/ to MongoDB with id 67427b05b98d7a37c0432f17\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/scenario_coverage/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/scenario_coverage/ to MongoDB with id 67427b06b98d7a37c0432f18\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/sbg_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/sbg_driver/ to MongoDB with id 67427b07b98d7a37c0432f19\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_visual_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_visual_tools/ to MongoDB with id 67427b08b98d7a37c0432f1a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_visual_testing_framework/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_visual_testing_framework/ to MongoDB with id 67427b09b98d7a37c0432f1b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_satellite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_satellite/ to MongoDB with id 67427b09b98d7a37c0432f1c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_rendering_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_rendering_tests/ to MongoDB with id 67427b0ab98d7a37c0432f1d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_rendering/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_rendering/ to MongoDB with id 67427b0ab98d7a37c0432f1e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_ogre_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_ogre_vendor/ to MongoDB with id 67427b0bb98d7a37c0432f1f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_imu_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_imu_plugin/ to MongoDB with id 67427b0bb98d7a37c0432f20\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_default_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_default_plugins/ to MongoDB with id 67427b0cb98d7a37c0432f21\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_assimp_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_assimp_vendor/ to MongoDB with id 67427b0db98d7a37c0432f22\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz_2d_overlay_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz_2d_overlay_plugins/ to MongoDB with id 67427b0db98d7a37c0432f23\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rviz2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rviz2/ to MongoDB with id 67427b0db98d7a37c0432f24\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rttest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rttest/ to MongoDB with id 67427b0eb98d7a37c0432f25\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rti_connext_dds_cmake_module/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rti_connext_dds_cmake_module/ to MongoDB with id 67427b0eb98d7a37c0432f26\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_viz/ to MongoDB with id 67427b0fb98d7a37c0432f27\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_util/ to MongoDB with id 67427b0fb98d7a37c0432f28\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_sync/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_sync/ to MongoDB with id 67427b10b98d7a37c0432f29\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_slam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_slam/ to MongoDB with id 67427b10b98d7a37c0432f2a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_rviz_plugins/ to MongoDB with id 67427b11b98d7a37c0432f2b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_ros/ to MongoDB with id 67427b11b98d7a37c0432f2c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_python/ to MongoDB with id 67427b12b98d7a37c0432f2d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_odom/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_odom/ to MongoDB with id 67427b12b98d7a37c0432f2e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_msgs/ to MongoDB with id 67427b12b98d7a37c0432f2f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_launch/ to MongoDB with id 67427b13b98d7a37c0432f30\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_examples/ to MongoDB with id 67427b13b98d7a37c0432f31\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_demos/ to MongoDB with id 67427b14b98d7a37c0432f32\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap_conversions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap_conversions/ to MongoDB with id 67427b15b98d7a37c0432f33\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rtabmap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rtabmap/ to MongoDB with id 67427b15b98d7a37c0432f34\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rt_usb_9axisimu_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rt_usb_9axisimu_driver/ to MongoDB with id 67427b15b98d7a37c0432f35\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rt_manipulators_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rt_manipulators_examples/ to MongoDB with id 67427b16b98d7a37c0432f36\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rt_manipulators_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rt_manipulators_cpp/ to MongoDB with id 67427b17b98d7a37c0432f37\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rsl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rsl/ to MongoDB with id 67427b17b98d7a37c0432f38\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_mocap4r2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_mocap4r2_control/ to MongoDB with id 67427b18b98d7a37c0432f39\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_joint_trajectory_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_joint_trajectory_controller/ to MongoDB with id 67427b18b98d7a37c0432f3a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_image_view/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_image_view/ to MongoDB with id 67427b19b98d7a37c0432f3b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_image_overlay_layer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_image_overlay_layer/ to MongoDB with id 67427b19b98d7a37c0432f3c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_gui_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_gui_cpp/ to MongoDB with id 67427b1ab98d7a37c0432f3d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_dotgraph/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_dotgraph/ to MongoDB with id 67427b1bb98d7a37c0432f3e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rqt_controller_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rqt_controller_manager/ to MongoDB with id 67427b1cb98d7a37c0432f3f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rplidar_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rplidar_ros/ to MongoDB with id 67427b1cb98d7a37c0432f40\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosx_introspection/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosx_introspection/ to MongoDB with id 67427b1db98d7a37c0432f41\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_introspection_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_introspection_tests/ to MongoDB with id 67427b1db98d7a37c0432f42\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_introspection_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_introspection_cpp/ to MongoDB with id 67427b1eb98d7a37c0432f43\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_introspection_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_introspection_c/ to MongoDB with id 67427b1eb98d7a37c0432f44\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_interface/ to MongoDB with id 67427b1fb98d7a37c0432f45\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_fastrtps_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_fastrtps_cpp/ to MongoDB with id 67427b1fb98d7a37c0432f46\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_fastrtps_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_fastrtps_c/ to MongoDB with id 67427b20b98d7a37c0432f47\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_cpp/ to MongoDB with id 67427b22b98d7a37c0432f48\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_typesupport_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_typesupport_c/ to MongoDB with id 67427b23b98d7a37c0432f49\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_runtime_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_runtime_cpp/ to MongoDB with id 67427b23b98d7a37c0432f4a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_runtime_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_runtime_c/ to MongoDB with id 67427b24b98d7a37c0432f4b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_parser/ to MongoDB with id 67427b25b98d7a37c0432f4c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_generator_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_generator_cpp/ to MongoDB with id 67427b25b98d7a37c0432f4d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_generator_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_generator_c/ to MongoDB with id 67427b25b98d7a37c0432f4e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_cmake/ to MongoDB with id 67427b26b98d7a37c0432f4f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_cli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_cli/ to MongoDB with id 67427b26b98d7a37c0432f50\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosidl_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosidl_adapter/ to MongoDB with id 67427b27b98d7a37c0432f51\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbridge_test_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbridge_test_msgs/ to MongoDB with id 67427b27b98d7a37c0432f52\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbridge_suite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbridge_suite/ to MongoDB with id 67427b28b98d7a37c0432f53\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbridge_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbridge_server/ to MongoDB with id 67427b28b98d7a37c0432f54\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbridge_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbridge_msgs/ to MongoDB with id 67427b29b98d7a37c0432f55\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbridge_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbridge_library/ to MongoDB with id 67427b29b98d7a37c0432f56\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_transport/ to MongoDB with id 67427b2ab98d7a37c0432f57\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_tests/ to MongoDB with id 67427b2ab98d7a37c0432f58\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_test_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_test_common/ to MongoDB with id 67427b2bb98d7a37c0432f59\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_storage_mcap_testdata/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_storage_mcap_testdata/ to MongoDB with id 67427b2bb98d7a37c0432f5a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_storage_mcap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_storage_mcap/ to MongoDB with id 67427b2cb98d7a37c0432f5b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_storage_default_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_storage_default_plugins/ to MongoDB with id 67427b2cb98d7a37c0432f5c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_storage/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_storage/ to MongoDB with id 67427b2db98d7a37c0432f5d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_py/ to MongoDB with id 67427b2db98d7a37c0432f5e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_performance_benchmarking/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_performance_benchmarking/ to MongoDB with id 67427b2eb98d7a37c0432f5f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_interfaces/ to MongoDB with id 67427b2eb98d7a37c0432f60\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_cpp/ to MongoDB with id 67427b2fb98d7a37c0432f61\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_compression_zstd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_compression_zstd/ to MongoDB with id 67427b2fb98d7a37c0432f62\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2_compression/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2_compression/ to MongoDB with id 67427b30b98d7a37c0432f63\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosbag2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosbag2/ to MongoDB with id 67427b30b98d7a37c0432f64\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosapi_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosapi_msgs/ to MongoDB with id 67427b31b98d7a37c0432f65\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rosapi/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rosapi/ to MongoDB with id 67427b31b98d7a37c0432f66\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_timer_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_timer_client/ to MongoDB with id 67427b32b98d7a37c0432f67\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_publisher_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_publisher_client/ to MongoDB with id 67427b32b98d7a37c0432f68\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_image_to_qimage/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_image_to_qimage/ to MongoDB with id 67427b33b98d7a37c0432f69\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_ign_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_ign_interfaces/ to MongoDB with id 67427b33b98d7a37c0432f6a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_ign_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_ign_image/ to MongoDB with id 67427b33b98d7a37c0432f6b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_ign_gazebo_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_ign_gazebo_demos/ to MongoDB with id 67427b34b98d7a37c0432f6c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_ign_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_ign_gazebo/ to MongoDB with id 67427b34b98d7a37c0432f6d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_ign_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_ign_bridge/ to MongoDB with id 67427b35b98d7a37c0432f6e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_ign/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_ign/ to MongoDB with id 67427b35b98d7a37c0432f6f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_gz_sim_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_gz_sim_demos/ to MongoDB with id 67427b36b98d7a37c0432f70\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_gz_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_gz_sim/ to MongoDB with id 67427b36b98d7a37c0432f71\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_gz_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_gz_interfaces/ to MongoDB with id 67427b37b98d7a37c0432f72\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_gz_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_gz_image/ to MongoDB with id 67427b37b98d7a37c0432f73\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_gz_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_gz_bridge/ to MongoDB with id 67427b38b98d7a37c0432f74\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_gz/ to MongoDB with id 67427b38b98d7a37c0432f75\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_babel_fish_test_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_babel_fish_test_msgs/ to MongoDB with id 67427b38b98d7a37c0432f76\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros_babel_fish/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros_babel_fish/ to MongoDB with id 67427b39b98d7a37c0432f77\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2trace_analysis/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2trace_analysis/ to MongoDB with id 67427b3ab98d7a37c0432f78\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2topic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2topic/ to MongoDB with id 67427b3ab98d7a37c0432f79\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2service/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2service/ to MongoDB with id 67427b3bb98d7a37c0432f7a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2run/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2run/ to MongoDB with id 67427b3bb98d7a37c0432f7b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2pkg/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2pkg/ to MongoDB with id 67427b3bb98d7a37c0432f7c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2param/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2param/ to MongoDB with id 67427b3cb98d7a37c0432f7d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2node/ to MongoDB with id 67427b3cb98d7a37c0432f7e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2multicast/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2multicast/ to MongoDB with id 67427b3db98d7a37c0432f7f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2lifecycle_test_fixtures/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2lifecycle_test_fixtures/ to MongoDB with id 67427b3db98d7a37c0432f80\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2lifecycle/ to MongoDB with id 67427b3eb98d7a37c0432f81\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2launch/ to MongoDB with id 67427b3eb98d7a37c0432f82\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2interface/ to MongoDB with id 67427b3fb98d7a37c0432f83\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2doctor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2doctor/ to MongoDB with id 67427b3fb98d7a37c0432f84\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2controlcli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2controlcli/ to MongoDB with id 67427b40b98d7a37c0432f85\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2component/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2component/ to MongoDB with id 67427b40b98d7a37c0432f86\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2cli_test_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2cli_test_interfaces/ to MongoDB with id 67427b41b98d7a37c0432f87\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2cli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2cli/ to MongoDB with id 67427b41b98d7a37c0432f88\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2caret/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2caret/ to MongoDB with id 67427b42b98d7a37c0432f89\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2bag/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2bag/ to MongoDB with id 67427b42b98d7a37c0432f8a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2action/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2action/ to MongoDB with id 67427b43b98d7a37c0432f8b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_socketcan_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_socketcan_msgs/ to MongoDB with id 67427b43b98d7a37c0432f8c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_socketcan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_socketcan/ to MongoDB with id 67427b43b98d7a37c0432f8d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_ouster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_ouster/ to MongoDB with id 67427b46b98d7a37c0432f8e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_controllers_test_nodes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_controllers_test_nodes/ to MongoDB with id 67427b46b98d7a37c0432f8f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_controllers/ to MongoDB with id 67427b46b98d7a37c0432f90\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_control_test_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_control_test_assets/ to MongoDB with id 67427b47b98d7a37c0432f91\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros2_control/ to MongoDB with id 67427b48b98d7a37c0432f92\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ros1_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ros1_bridge/ to MongoDB with id 67427b48b98d7a37c0432f93\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robotont_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robotont_driver/ to MongoDB with id 67427b49b98d7a37c0432f94\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robotiq_hardware_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robotiq_hardware_tests/ to MongoDB with id 67427b49b98d7a37c0432f95\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robotiq_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robotiq_driver/ to MongoDB with id 67427b4ab98d7a37c0432f96\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robotiq_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robotiq_description/ to MongoDB with id 67427b4ab98d7a37c0432f97\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robotiq_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robotiq_controllers/ to MongoDB with id 67427b4bb98d7a37c0432f98\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robot_state_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robot_state_publisher/ to MongoDB with id 67427b4bb98d7a37c0432f99\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robot_controllers_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robot_controllers_msgs/ to MongoDB with id 67427b4cb98d7a37c0432f9a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robot_controllers_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robot_controllers_interface/ to MongoDB with id 67427b4cb98d7a37c0432f9b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robot_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robot_controllers/ to MongoDB with id 67427b4db98d7a37c0432f9c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robot_calibration_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robot_calibration_msgs/ to MongoDB with id 67427b4db98d7a37c0432f9d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robot_calibration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robot_calibration/ to MongoDB with id 67427b4eb98d7a37c0432f9e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/robosoft_openai/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/robosoft_openai/ to MongoDB with id 67427b4eb98d7a37c0432f9f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_implementation_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_implementation_cmake/ to MongoDB with id 67427b4fb98d7a37c0432fa0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_implementation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_implementation/ to MongoDB with id 67427b4fb98d7a37c0432fa1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_gurumdds_shared_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_gurumdds_shared_cpp/ to MongoDB with id 67427b50b98d7a37c0432fa2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_gurumdds_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_gurumdds_cpp/ to MongoDB with id 67427b51b98d7a37c0432fa3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_fastrtps_shared_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_fastrtps_shared_cpp/ to MongoDB with id 67427b52b98d7a37c0432fa4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_fastrtps_dynamic_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_fastrtps_dynamic_cpp/ to MongoDB with id 67427b52b98d7a37c0432fa5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_fastrtps_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_fastrtps_cpp/ to MongoDB with id 67427b53b98d7a37c0432fa6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_dds_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_dds_common/ to MongoDB with id 67427b53b98d7a37c0432fa7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_connextddsmicro/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_connextddsmicro/ to MongoDB with id 67427b54b98d7a37c0432fa8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_connextdds_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_connextdds_common/ to MongoDB with id 67427b54b98d7a37c0432fa9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw_connextdds/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw_connextdds/ to MongoDB with id 67427b55b98d7a37c0432faa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmw/ to MongoDB with id 67427b55b98d7a37c0432fab\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_workcell_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_workcell_msgs/ to MongoDB with id 67427b56b98d7a37c0432fac\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_websocket/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_websocket/ to MongoDB with id 67427b56b98d7a37c0432fad\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization_rviz2_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization_rviz2_plugins/ to MongoDB with id 67427b57b98d7a37c0432fae\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization_obstacles/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization_obstacles/ to MongoDB with id 67427b57b98d7a37c0432faf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization_navgraphs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization_navgraphs/ to MongoDB with id 67427b58b98d7a37c0432fb0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization_floorplans/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization_floorplans/ to MongoDB with id 67427b58b98d7a37c0432fb1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization_fleet_states/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization_fleet_states/ to MongoDB with id 67427b59b98d7a37c0432fb2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization_building_systems/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization_building_systems/ to MongoDB with id 67427b59b98d7a37c0432fb3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_visualization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_visualization/ to MongoDB with id 67427b59b98d7a37c0432fb4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_utils/ to MongoDB with id 67427b5ab98d7a37c0432fb5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_traffic_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_traffic_ros2/ to MongoDB with id 67427b5bb98d7a37c0432fb6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_traffic_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_traffic_msgs/ to MongoDB with id 67427b5cb98d7a37c0432fb7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_traffic_editor_test_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_traffic_editor_test_maps/ to MongoDB with id 67427b5cb98d7a37c0432fb8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_traffic_editor_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_traffic_editor_assets/ to MongoDB with id 67427b5db98d7a37c0432fb9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_traffic_editor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_traffic_editor/ to MongoDB with id 67427b5db98d7a37c0432fba\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_traffic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_traffic/ to MongoDB with id 67427b5eb98d7a37c0432fbb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_task_sequence/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_task_sequence/ to MongoDB with id 67427b5fb98d7a37c0432fbc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_task_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_task_ros2/ to MongoDB with id 67427b5fb98d7a37c0432fbd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_task_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_task_msgs/ to MongoDB with id 67427b60b98d7a37c0432fbe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_task/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_task/ to MongoDB with id 67427b61b98d7a37c0432fbf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_site_map_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_site_map_msgs/ to MongoDB with id 67427b61b98d7a37c0432fc0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_scheduler_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_scheduler_msgs/ to MongoDB with id 67427b61b98d7a37c0432fc1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_robot_sim_gz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_robot_sim_gz_plugins/ to MongoDB with id 67427b62b98d7a37c0432fc2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_robot_sim_gz_classic_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_robot_sim_gz_classic_plugins/ to MongoDB with id 67427b62b98d7a37c0432fc3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_robot_sim_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_robot_sim_common/ to MongoDB with id 67427b63b98d7a37c0432fc4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_obstacle_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_obstacle_msgs/ to MongoDB with id 67427b63b98d7a37c0432fc5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_lift_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_lift_msgs/ to MongoDB with id 67427b64b98d7a37c0432fc6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_ingestor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_ingestor_msgs/ to MongoDB with id 67427b64b98d7a37c0432fc7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_fleet_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_fleet_msgs/ to MongoDB with id 67427b65b98d7a37c0432fc8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_fleet_adapter_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_fleet_adapter_python/ to MongoDB with id 67427b65b98d7a37c0432fc9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_fleet_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_fleet_adapter/ to MongoDB with id 67427b66b98d7a37c0432fca\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_door_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_door_msgs/ to MongoDB with id 67427b66b98d7a37c0432fcb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_dispenser_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_dispenser_msgs/ to MongoDB with id 67427b67b98d7a37c0432fcc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_dev/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_dev/ to MongoDB with id 67427b67b98d7a37c0432fcd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_tasks/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_tasks/ to MongoDB with id 67427b68b98d7a37c0432fce\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_panel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_panel/ to MongoDB with id 67427b68b98d7a37c0432fcf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_maps/ to MongoDB with id 67427b69b98d7a37c0432fd0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_gz_classic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_gz_classic/ to MongoDB with id 67427b69b98d7a37c0432fd1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_gz/ to MongoDB with id 67427b69b98d7a37c0432fd2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_fleet_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_fleet_adapter/ to MongoDB with id 67427b6ab98d7a37c0432fd3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_dashboard_resources/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_dashboard_resources/ to MongoDB with id 67427b6ab98d7a37c0432fd4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_bridges/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_bridges/ to MongoDB with id 67427b6bb98d7a37c0432fd5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos_assets/ to MongoDB with id 67427b6cb98d7a37c0432fd6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_demos/ to MongoDB with id 67427b6cb98d7a37c0432fd7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_charger_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_charger_msgs/ to MongoDB with id 67427b6db98d7a37c0432fd8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_building_sim_gz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_building_sim_gz_plugins/ to MongoDB with id 67427b6db98d7a37c0432fd9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_building_sim_gz_classic_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_building_sim_gz_classic_plugins/ to MongoDB with id 67427b6db98d7a37c0432fda\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_building_sim_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_building_sim_common/ to MongoDB with id 67427b6eb98d7a37c0432fdb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_building_map_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_building_map_tools/ to MongoDB with id 67427b6eb98d7a37c0432fdc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rmf_battery/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rmf_battery/ to MongoDB with id 67427b6fb98d7a37c0432fdd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/resource_retriever/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/resource_retriever/ to MongoDB with id 67427b6fb98d7a37c0432fde\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/realtime_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/realtime_tools/ to MongoDB with id 67427b70b98d7a37c0432fdf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/realsense2_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/realsense2_description/ to MongoDB with id 67427b70b98d7a37c0432fe0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/realsense2_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/realsense2_camera_msgs/ to MongoDB with id 67427b71b98d7a37c0432fe1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/realsense2_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/realsense2_camera/ to MongoDB with id 67427b71b98d7a37c0432fe2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcutils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcutils/ to MongoDB with id 67427b72b98d7a37c0432fe3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcss3d_agent_basic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcss3d_agent_basic/ to MongoDB with id 67427b72b98d7a37c0432fe4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcss3d_agent/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcss3d_agent/ to MongoDB with id 67427b73b98d7a37c0432fe5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcpputils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcpputils/ to MongoDB with id 67427b73b98d7a37c0432fe6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclpy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclpy/ to MongoDB with id 67427b74b98d7a37c0432fe7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclcpp_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclcpp_lifecycle/ to MongoDB with id 67427b74b98d7a37c0432fe8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclcpp_components/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclcpp_components/ to MongoDB with id 67427b75b98d7a37c0432fe9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclcpp_cascade_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclcpp_cascade_lifecycle/ to MongoDB with id 67427b75b98d7a37c0432fea\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclcpp_action/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclcpp_action/ to MongoDB with id 67427b76b98d7a37c0432feb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclcpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclcpp/ to MongoDB with id 67427b76b98d7a37c0432fec\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclc_parameter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclc_parameter/ to MongoDB with id 67427b77b98d7a37c0432fed\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclc_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclc_lifecycle/ to MongoDB with id 67427b77b98d7a37c0432fee\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rclc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rclc/ to MongoDB with id 67427b78b98d7a37c0432fef\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl_yaml_param_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl_yaml_param_parser/ to MongoDB with id 67427b78b98d7a37c0432ff0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl_logging_spdlog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl_logging_spdlog/ to MongoDB with id 67427b79b98d7a37c0432ff1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl_logging_noop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl_logging_noop/ to MongoDB with id 67427b79b98d7a37c0432ff2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl_logging_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl_logging_interface/ to MongoDB with id 67427b7ab98d7a37c0432ff3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl_lifecycle/ to MongoDB with id 67427b7ab98d7a37c0432ff4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl_action/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl_action/ to MongoDB with id 67427b7bb98d7a37c0432ff5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcl/ to MongoDB with id 67427b7bb98d7a37c0432ff6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcgcrd_spl_4_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcgcrd_spl_4_conversion/ to MongoDB with id 67427b7cb98d7a37c0432ff7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcgcd_spl_14_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcgcd_spl_14_conversion/ to MongoDB with id 67427b7cb98d7a37c0432ff8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rcdiscover/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rcdiscover/ to MongoDB with id 67427b7db98d7a37c0432ff9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rc_reason_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rc_reason_msgs/ to MongoDB with id 67427b7db98d7a37c0432ffa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rc_reason_clients/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rc_reason_clients/ to MongoDB with id 67427b7eb98d7a37c0432ffb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rc_genicam_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rc_genicam_driver/ to MongoDB with id 67427b7fb98d7a37c0432ffc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/rc_genicam_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/rc_genicam_api/ to MongoDB with id 67427b7fb98d7a37c0432ffd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/raspimouse_ros2_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/raspimouse_ros2_examples/ to MongoDB with id 67427b80b98d7a37c0432ffe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/raspimouse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/raspimouse/ to MongoDB with id 67427b80b98d7a37c0432fff\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/range_sensor_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/range_sensor_broadcaster/ to MongoDB with id 67427b81b98d7a37c0433000\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/random_numbers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/random_numbers/ to MongoDB with id 67427b81b98d7a37c0433001\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/r2r_spl_8/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/r2r_spl_8/ to MongoDB with id 67427b82b98d7a37c0433002\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/r2r_spl_7/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/r2r_spl_7/ to MongoDB with id 67427b82b98d7a37c0433003\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/r2r_spl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/r2r_spl/ to MongoDB with id 67427b83b98d7a37c0433004\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/quality_of_service_demo_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/quality_of_service_demo_py/ to MongoDB with id 67427b83b98d7a37c0433005\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/quality_of_service_demo_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/quality_of_service_demo_cpp/ to MongoDB with id 67427b83b98d7a37c0433006\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/qt_gui_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/qt_gui_cpp/ to MongoDB with id 67427b84b98d7a37c0433007\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/python_mrpt/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/python_mrpt/ to MongoDB with id 67427b84b98d7a37c0433008\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pyhri/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pyhri/ to MongoDB with id 67427b85b98d7a37c0433009\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pure_spinning_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pure_spinning_local_planner/ to MongoDB with id 67427b85b98d7a37c043300a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/puma_motor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/puma_motor_msgs/ to MongoDB with id 67427b86b98d7a37c043300b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/puma_motor_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/puma_motor_driver/ to MongoDB with id 67427b87b98d7a37c043300c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ptz_action_server_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ptz_action_server_msgs/ to MongoDB with id 67427b87b98d7a37c043300d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/psdk_wrapper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/psdk_wrapper/ to MongoDB with id 67427b88b98d7a37c043300e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/psdk_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/psdk_interfaces/ to MongoDB with id 67427b88b98d7a37c043300f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/proxsuite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/proxsuite/ to MongoDB with id 67427b89b98d7a37c0433010\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/position_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/position_controllers/ to MongoDB with id 67427b8ab98d7a37c0433011\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pose_cov_ops/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pose_cov_ops/ to MongoDB with id 67427b8ab98d7a37c0433012\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pose_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pose_broadcaster/ to MongoDB with id 67427b8bb98d7a37c0433013\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/polygon_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/polygon_utils/ to MongoDB with id 67427b8bb98d7a37c0433014\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/polygon_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/polygon_rviz_plugins/ to MongoDB with id 67427b8cb98d7a37c0433015\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/polygon_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/polygon_msgs/ to MongoDB with id 67427b8cb98d7a37c0433016\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/polygon_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/polygon_demos/ to MongoDB with id 67427b8db98d7a37c0433017\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pointcloud_to_laserscan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pointcloud_to_laserscan/ to MongoDB with id 67427b8db98d7a37c0433018\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/point_cloud_transport_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/point_cloud_transport_py/ to MongoDB with id 67427b8eb98d7a37c0433019\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/point_cloud_transport_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/point_cloud_transport_plugins/ to MongoDB with id 67427b8eb98d7a37c043301a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/point_cloud_transport/ to MongoDB with id 67427b8eb98d7a37c043301b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/point_cloud_msg_wrapper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/point_cloud_msg_wrapper/ to MongoDB with id 67427b8fb98d7a37c043301c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/point_cloud_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/point_cloud_interfaces/ to MongoDB with id 67427b90b98d7a37c043301d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_simulation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_simulation/ to MongoDB with id 67427b90b98d7a37c043301e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_robot/ to MongoDB with id 67427b90b98d7a37c043301f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_rgbd_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_rgbd_sensors/ to MongoDB with id 67427b91b98d7a37c0433020\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_navigation/ to MongoDB with id 67427b92b98d7a37c0433021\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_laser_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_laser_sensors/ to MongoDB with id 67427b92b98d7a37c0433022\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_gazebo/ to MongoDB with id 67427b93b98d7a37c0433023\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_description/ to MongoDB with id 67427b93b98d7a37c0433024\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_controller_configuration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_controller_configuration/ to MongoDB with id 67427b94b98d7a37c0433025\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_bringup/ to MongoDB with id 67427b94b98d7a37c0433026\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pmb2_2dnav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pmb2_2dnav/ to MongoDB with id 67427b95b98d7a37c0433027\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pluginlib/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pluginlib/ to MongoDB with id 67427b95b98d7a37c0433028\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plotjuggler_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plotjuggler_ros/ to MongoDB with id 67427b96b98d7a37c0433029\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plotjuggler/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plotjuggler/ to MongoDB with id 67427b96b98d7a37c043302a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/play_motion2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/play_motion2_msgs/ to MongoDB with id 67427b97b98d7a37c043302b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/play_motion2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/play_motion2/ to MongoDB with id 67427b97b98d7a37c043302c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_tools/ to MongoDB with id 67427b98b98d7a37c043302d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_tests/ to MongoDB with id 67427b98b98d7a37c043302e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_terminal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_terminal/ to MongoDB with id 67427b98b98d7a37c043302f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_problem_expert/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_problem_expert/ to MongoDB with id 67427b99b98d7a37c0433030\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_popf_plan_solver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_popf_plan_solver/ to MongoDB with id 67427b99b98d7a37c0433031\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_planner/ to MongoDB with id 67427b9ab98d7a37c0433032\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_pddl_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_pddl_parser/ to MongoDB with id 67427b9ab98d7a37c0433033\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_msgs/ to MongoDB with id 67427b9bb98d7a37c0433034\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_lifecycle_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_lifecycle_manager/ to MongoDB with id 67427b9bb98d7a37c0433035\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_executor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_executor/ to MongoDB with id 67427b9cb98d7a37c0433036\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_domain_expert/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_domain_expert/ to MongoDB with id 67427b9db98d7a37c0433037\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_core/ to MongoDB with id 67427b9db98d7a37c0433038\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_bt_actions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_bt_actions/ to MongoDB with id 67427b9eb98d7a37c0433039\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/plansys2_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/plansys2_bringup/ to MongoDB with id 67427b9eb98d7a37c043303a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pilz_industrial_motion_planner_testutils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pilz_industrial_motion_planner_testutils/ to MongoDB with id 67427b9fb98d7a37c043303b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pilz_industrial_motion_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pilz_industrial_motion_planner/ to MongoDB with id 67427b9fb98d7a37c043303c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pid_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pid_controller/ to MongoDB with id 67427ba0b98d7a37c043303d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/picknik_twist_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/picknik_twist_controller/ to MongoDB with id 67427ba0b98d7a37c043303e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/picknik_reset_fault_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/picknik_reset_fault_controller/ to MongoDB with id 67427ba1b98d7a37c043303f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pick_ik/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pick_ik/ to MongoDB with id 67427ba1b98d7a37c0433040\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_temperature/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_temperature/ to MongoDB with id 67427ba2b98d7a37c0433041\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_spatial/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_spatial/ to MongoDB with id 67427ba2b98d7a37c0433042\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_motors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_motors/ to MongoDB with id 67427ba3b98d7a37c0433043\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_magnetometer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_magnetometer/ to MongoDB with id 67427ba3b98d7a37c0433044\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_high_speed_encoder/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_high_speed_encoder/ to MongoDB with id 67427ba4b98d7a37c0433045\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_gyroscope/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_gyroscope/ to MongoDB with id 67427ba4b98d7a37c0433046\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_digital_outputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_digital_outputs/ to MongoDB with id 67427ba4b98d7a37c0433047\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_digital_inputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_digital_inputs/ to MongoDB with id 67427ba5b98d7a37c0433048\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_api/ to MongoDB with id 67427ba6b98d7a37c0433049\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_analog_outputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_analog_outputs/ to MongoDB with id 67427ba6b98d7a37c043304a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_analog_inputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_analog_inputs/ to MongoDB with id 67427ba6b98d7a37c043304b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/phidgets_accelerometer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/phidgets_accelerometer/ to MongoDB with id 67427ba7b98d7a37c043304c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/performance_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/performance_test/ to MongoDB with id 67427ba7b98d7a37c043304d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/performance_report/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/performance_report/ to MongoDB with id 67427ba8b98d7a37c043304e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/perception_pcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/perception_pcl/ to MongoDB with id 67427ba9b98d7a37c043304f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pendulum_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pendulum_msgs/ to MongoDB with id 67427ba9b98d7a37c0433050\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pendulum_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pendulum_control/ to MongoDB with id 67427baab98d7a37c0433051\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pcl_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pcl_ros/ to MongoDB with id 67427baab98d7a37c0433052\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pcl_conversions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pcl_conversions/ to MongoDB with id 67427babb98d7a37c0433053\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/parameter_traits/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/parameter_traits/ to MongoDB with id 67427babb98d7a37c0433054\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/panda_arm_2_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/panda_arm_2_moveit_config/ to MongoDB with id 67427bacb98d7a37c0433055\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/panda_arm_1_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/panda_arm_1_moveit_config/ to MongoDB with id 67427bacb98d7a37c0433056\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_statistics_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_statistics_msgs/ to MongoDB with id 67427bacb98d7a37c0433057\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_statistics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_statistics/ to MongoDB with id 67427badb98d7a37c0433058\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_robotiq_gripper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_robotiq_gripper/ to MongoDB with id 67427badb98d7a37c0433059\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_robotiq_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_robotiq_description/ to MongoDB with id 67427baeb98d7a37c043305a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_robotiq_controller_configuration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_robotiq_controller_configuration/ to MongoDB with id 67427baeb98d7a37c043305b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_maps/ to MongoDB with id 67427baeb98d7a37c043305c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_hey5_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_hey5_description/ to MongoDB with id 67427bafb98d7a37c043305d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_hey5_controller_configuration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_hey5_controller_configuration/ to MongoDB with id 67427bafb98d7a37c043305e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_hey5/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_hey5/ to MongoDB with id 67427bb0b98d7a37c043305f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_gripper_simulation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_gripper_simulation/ to MongoDB with id 67427bb1b98d7a37c0433060\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_gripper_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_gripper_description/ to MongoDB with id 67427bb1b98d7a37c0433061\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_gripper_controller_configuration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_gripper_controller_configuration/ to MongoDB with id 67427bb2b98d7a37c0433062\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_gripper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_gripper/ to MongoDB with id 67427bb2b98d7a37c0433063\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/pal_gazebo_worlds/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/pal_gazebo_worlds/ to MongoDB with id 67427bb3b98d7a37c0433064\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/osrf_testing_tools_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/osrf_testing_tools_cpp/ to MongoDB with id 67427bb4b98d7a37c0433065\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/osrf_pycommon/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/osrf_pycommon/ to MongoDB with id 67427bb4b98d7a37c0433066\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/openvdb_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/openvdb_vendor/ to MongoDB with id 67427bb5b98d7a37c0433067\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/openni2_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/openni2_camera/ to MongoDB with id 67427bb5b98d7a37c0433068\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/opennav_docking_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/opennav_docking_msgs/ to MongoDB with id 67427bb5b98d7a37c0433069\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/opennav_docking_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/opennav_docking_core/ to MongoDB with id 67427bb6b98d7a37c043306a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/opennav_docking_bt/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/opennav_docking_bt/ to MongoDB with id 67427bb6b98d7a37c043306b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/opennav_docking/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/opennav_docking/ to MongoDB with id 67427bb7b98d7a37c043306c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/openeb_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/openeb_vendor/ to MongoDB with id 67427bb7b98d7a37c043306d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_simulation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_simulation/ to MongoDB with id 67427bb8b98d7a37c043306e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_robot/ to MongoDB with id 67427bb8b98d7a37c043306f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_rgbd_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_rgbd_sensors/ to MongoDB with id 67427bb8b98d7a37c0433070\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_navigation/ to MongoDB with id 67427bb9b98d7a37c0433071\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_laser_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_laser_sensors/ to MongoDB with id 67427bb9b98d7a37c0433072\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_gazebo/ to MongoDB with id 67427bbab98d7a37c0433073\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_description/ to MongoDB with id 67427bbbb98d7a37c0433074\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_controller_configuration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_controller_configuration/ to MongoDB with id 67427bbbb98d7a37c0433075\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_bringup/ to MongoDB with id 67427bbbb98d7a37c0433076\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/omni_base_2dnav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/omni_base_2dnav/ to MongoDB with id 67427bbcb98d7a37c0433077\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_uss_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_uss_msgs/ to MongoDB with id 67427bbcb98d7a37c0433078\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_uss/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_uss/ to MongoDB with id 67427bbdb98d7a37c0433079\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_sensor_drivers_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_sensor_drivers_examples/ to MongoDB with id 67427bbdb98d7a37c043307a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_sensor_drivers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_sensor_drivers/ to MongoDB with id 67427bbeb98d7a37c043307b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_radar_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_radar_msgs/ to MongoDB with id 67427bbeb98d7a37c043307c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_radar/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_radar/ to MongoDB with id 67427bbfb98d7a37c043307d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_premium_radar_sample_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_premium_radar_sample_msgs/ to MongoDB with id 67427bbfb98d7a37c043307e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_premium_radar_sample/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_premium_radar_sample/ to MongoDB with id 67427bc0b98d7a37c043307f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_premium_radar/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_premium_radar/ to MongoDB with id 67427bc1b98d7a37c0433080\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_general_purpose_radar_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_general_purpose_radar_msgs/ to MongoDB with id 67427bc2b98d7a37c0433081\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_general_purpose_radar/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_general_purpose_radar/ to MongoDB with id 67427bc2b98d7a37c0433082\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/off_highway_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/off_highway_can/ to MongoDB with id 67427bc3b98d7a37c0433083\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/odom_to_tf_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/odom_to_tf_ros2/ to MongoDB with id 67427bc3b98d7a37c0433084\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octovis/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octovis/ to MongoDB with id 67427bc4b98d7a37c0433085\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octomap_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octomap_server/ to MongoDB with id 67427bc4b98d7a37c0433086\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octomap_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octomap_rviz_plugins/ to MongoDB with id 67427bc5b98d7a37c0433087\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octomap_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octomap_ros/ to MongoDB with id 67427bc5b98d7a37c0433088\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octomap_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octomap_msgs/ to MongoDB with id 67427bc6b98d7a37c0433089\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octomap_mapping/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octomap_mapping/ to MongoDB with id 67427bc6b98d7a37c043308a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/octomap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/octomap/ to MongoDB with id 67427bc7b98d7a37c043308b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ntrip_client_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ntrip_client_node/ to MongoDB with id 67427bc7b98d7a37c043308c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ntpd_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ntpd_driver/ to MongoDB with id 67427bc8b98d7a37c043308d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/novatel_oem7_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/novatel_oem7_msgs/ to MongoDB with id 67427bc8b98d7a37c043308e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/novatel_oem7_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/novatel_oem7_driver/ to MongoDB with id 67427bc9b98d7a37c043308f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/novatel_gps_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/novatel_gps_msgs/ to MongoDB with id 67427bc9b98d7a37c0433090\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/novatel_gps_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/novatel_gps_driver/ to MongoDB with id 67427bcab98d7a37c0433091\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nova_carter_docking/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nova_carter_docking/ to MongoDB with id 67427bcab98d7a37c0433092\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nmea_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nmea_msgs/ to MongoDB with id 67427bcbb98d7a37c0433093\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nmea_hardware_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nmea_hardware_interface/ to MongoDB with id 67427bcbb98d7a37c0433094\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nitrosz_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nitrosz_client/ to MongoDB with id 67427bccb98d7a37c0433095\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nicla_vision_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nicla_vision_ros2/ to MongoDB with id 67427bccb98d7a37c0433096\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nerian_stereo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nerian_stereo/ to MongoDB with id 67427bcdb98d7a37c0433097\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/neobotix_usboard_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/neobotix_usboard_msgs/ to MongoDB with id 67427bcdb98d7a37c0433098\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/neo_simulation2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/neo_simulation2/ to MongoDB with id 67427bceb98d7a37c0433099\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/neo_nav2_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/neo_nav2_bringup/ to MongoDB with id 67427bceb98d7a37c043309a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ndt_omp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ndt_omp/ to MongoDB with id 67427bceb98d7a37c043309b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/navigation2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/navigation2/ to MongoDB with id 67427bcfb98d7a37c043309c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav_msgs/ to MongoDB with id 67427bcfb98d7a37c043309d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav_2d_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav_2d_utils/ to MongoDB with id 67427bd0b98d7a37c043309e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav_2d_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav_2d_msgs/ to MongoDB with id 67427bd0b98d7a37c043309f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2z_planners_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2z_planners_common/ to MongoDB with id 67427bd1b98d7a37c04330a0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2z_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2z_client/ to MongoDB with id 67427bd1b98d7a37c04330a1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_waypoint_follower/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_waypoint_follower/ to MongoDB with id 67427bd2b98d7a37c04330a2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_voxel_grid/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_voxel_grid/ to MongoDB with id 67427bd2b98d7a37c04330a3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_velocity_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_velocity_smoother/ to MongoDB with id 67427bd3b98d7a37c04330a4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_util/ to MongoDB with id 67427bd3b98d7a37c04330a5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_theta_star_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_theta_star_planner/ to MongoDB with id 67427bd4b98d7a37c04330a6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_system_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_system_tests/ to MongoDB with id 67427bd4b98d7a37c04330a7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_smoother/ to MongoDB with id 67427bd5b98d7a37c04330a8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_smac_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_smac_planner/ to MongoDB with id 67427bd5b98d7a37c04330a9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_simple_commander/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_simple_commander/ to MongoDB with id 67427bd6b98d7a37c04330aa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_rviz_plugins/ to MongoDB with id 67427bd6b98d7a37c04330ab\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_rotation_shim_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_rotation_shim_controller/ to MongoDB with id 67427bd7b98d7a37c04330ac\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_regulated_pure_pursuit_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_regulated_pure_pursuit_controller/ to MongoDB with id 67427bd8b98d7a37c04330ad\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_planner/ to MongoDB with id 67427bd8b98d7a37c04330ae\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_navfn_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_navfn_planner/ to MongoDB with id 67427bd8b98d7a37c04330af\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_msgs/ to MongoDB with id 67427bd9b98d7a37c04330b0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_mppi_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_mppi_controller/ to MongoDB with id 67427bdab98d7a37c04330b1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_map_server/ to MongoDB with id 67427bdab98d7a37c04330b2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_lifecycle_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_lifecycle_manager/ to MongoDB with id 67427bdbb98d7a37c04330b3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_graceful_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_graceful_controller/ to MongoDB with id 67427bdbb98d7a37c04330b4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_dwb_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_dwb_controller/ to MongoDB with id 67427bdcb98d7a37c04330b5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_core/ to MongoDB with id 67427bdcb98d7a37c04330b6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_controller/ to MongoDB with id 67427bdcb98d7a37c04330b7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_constrained_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_constrained_smoother/ to MongoDB with id 67427bddb98d7a37c04330b8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_common/ to MongoDB with id 67427bddb98d7a37c04330b9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_collision_monitor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_collision_monitor/ to MongoDB with id 67427bdeb98d7a37c04330ba\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_bt_navigator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_bt_navigator/ to MongoDB with id 67427bdeb98d7a37c04330bb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_bringup/ to MongoDB with id 67427bdfb98d7a37c04330bc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_behaviors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_behaviors/ to MongoDB with id 67427bdfb98d7a37c04330bd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_behavior_tree/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_behavior_tree/ to MongoDB with id 67427be0b98d7a37c04330be\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nav2_amcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nav2_amcl/ to MongoDB with id 67427be0b98d7a37c04330bf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nao_lola/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nao_lola/ to MongoDB with id 67427be1b98d7a37c04330c0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/nao_button_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/nao_button_sim/ to MongoDB with id 67427be1b98d7a37c04330c1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/myactuator_rmd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/myactuator_rmd/ to MongoDB with id 67427be2b98d7a37c04330c2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mvsim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mvsim/ to MongoDB with id 67427be2b98d7a37c04330c3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/multirole_sensor_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/multirole_sensor_client/ to MongoDB with id 67427be3b98d7a37c04330c4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/multires_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/multires_image/ to MongoDB with id 67427be3b98d7a37c04330c5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrt_cmake_modules/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrt_cmake_modules/ to MongoDB with id 67427be4b98d7a37c04330c6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_tutorials/ to MongoDB with id 67427be4b98d7a37c04330c7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_tps_astar_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_tps_astar_planner/ to MongoDB with id 67427be5b98d7a37c04330c8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_tclap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_tclap/ to MongoDB with id 67427be5b98d7a37c04330c9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_slam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_slam/ to MongoDB with id 67427be5b98d7a37c04330ca\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensors/ to MongoDB with id 67427be6b98d7a37c04330cb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensorlib/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensorlib/ to MongoDB with id 67427be6b98d7a37c04330cc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensor_imu_taobotics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensor_imu_taobotics/ to MongoDB with id 67427be7b98d7a37c04330cd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensor_gnss_novatel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensor_gnss_novatel/ to MongoDB with id 67427be7b98d7a37c04330ce\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensor_gnss_nmea/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensor_gnss_nmea/ to MongoDB with id 67427be8b98d7a37c04330cf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensor_gnns_novatel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensor_gnns_novatel/ to MongoDB with id 67427be8b98d7a37c04330d0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensor_gnns_nmea/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensor_gnns_nmea/ to MongoDB with id 67427be8b98d7a37c04330d1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_sensor_bumblebee_stereo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_sensor_bumblebee_stereo/ to MongoDB with id 67427be9b98d7a37c04330d2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_ros2bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_ros2bridge/ to MongoDB with id 67427be9b98d7a37c04330d3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_reactivenav2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_reactivenav2d/ to MongoDB with id 67427beab98d7a37c04330d4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_rawlog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_rawlog/ to MongoDB with id 67427beab98d7a37c04330d5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_poses/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_poses/ to MongoDB with id 67427bebb98d7a37c04330d6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_pointcloud_pipeline/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_pointcloud_pipeline/ to MongoDB with id 67427bebb98d7a37c04330d7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_pf_localization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_pf_localization/ to MongoDB with id 67427becb98d7a37c04330d8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_opengl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_opengl/ to MongoDB with id 67427becb98d7a37c04330d9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_obs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_obs/ to MongoDB with id 67427bedb98d7a37c04330da\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_navigation/ to MongoDB with id 67427bedb98d7a37c04330db\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_nav_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_nav_interfaces/ to MongoDB with id 67427bedb98d7a37c04330dc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_nav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_nav/ to MongoDB with id 67427beeb98d7a37c04330dd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_msgs_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_msgs_bridge/ to MongoDB with id 67427beeb98d7a37c04330de\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_msgs/ to MongoDB with id 67427befb98d7a37c04330df\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_math/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_math/ to MongoDB with id 67427befb98d7a37c04330e0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_maps/ to MongoDB with id 67427bf0b98d7a37c04330e1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_map_server/ to MongoDB with id 67427bf0b98d7a37c04330e2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libtclap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libtclap/ to MongoDB with id 67427bf1b98d7a37c04330e3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libslam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libslam/ to MongoDB with id 67427bf1b98d7a37c04330e4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libros_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libros_bridge/ to MongoDB with id 67427bf2b98d7a37c04330e5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libros2bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libros2bridge/ to MongoDB with id 67427bf2b98d7a37c04330e6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libposes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libposes/ to MongoDB with id 67427bf2b98d7a37c04330e7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libopengl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libopengl/ to MongoDB with id 67427bf3b98d7a37c04330e8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libobs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libobs/ to MongoDB with id 67427bf3b98d7a37c04330e9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libnav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libnav/ to MongoDB with id 67427bf4b98d7a37c04330ea\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libmath/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libmath/ to MongoDB with id 67427bf4b98d7a37c04330eb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libmaps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libmaps/ to MongoDB with id 67427bf5b98d7a37c04330ec\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libhwdrivers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libhwdrivers/ to MongoDB with id 67427bf5b98d7a37c04330ed\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libgui/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libgui/ to MongoDB with id 67427bf5b98d7a37c04330ee\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libbase/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libbase/ to MongoDB with id 67427bf6b98d7a37c04330ef\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_libapps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_libapps/ to MongoDB with id 67427bf6b98d7a37c04330f0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_hwdrivers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_hwdrivers/ to MongoDB with id 67427bf7b98d7a37c04330f1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_gui/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_gui/ to MongoDB with id 67427bf7b98d7a37c04330f2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_generic_sensor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_generic_sensor/ to MongoDB with id 67427bf8b98d7a37c04330f3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_base/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_base/ to MongoDB with id 67427bf8b98d7a37c04330f4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mrpt_apps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mrpt_apps/ to MongoDB with id 67427bf8b98d7a37c04330f5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mqtt_client_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mqtt_client_interfaces/ to MongoDB with id 67427bf9b98d7a37c04330f6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mqtt_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mqtt_client/ to MongoDB with id 67427bfab98d7a37c04330f7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mp2p_icp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mp2p_icp/ to MongoDB with id 67427bfbb98d7a37c04330f8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_visual_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_visual_tools/ to MongoDB with id 67427bfbb98d7a37c04330f9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_simple_controller_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_simple_controller_manager/ to MongoDB with id 67427bfcb98d7a37c04330fa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_setup_srdf_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_setup_srdf_plugins/ to MongoDB with id 67427bfcb98d7a37c04330fb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_setup_framework/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_setup_framework/ to MongoDB with id 67427bfdb98d7a37c04330fc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_setup_core_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_setup_core_plugins/ to MongoDB with id 67427bfeb98d7a37c04330fd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_setup_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_setup_controllers/ to MongoDB with id 67427bfeb98d7a37c04330fe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_setup_assistant/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_setup_assistant/ to MongoDB with id 67427bffb98d7a37c04330ff\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_setup_app_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_setup_app_plugins/ to MongoDB with id 67427bffb98d7a37c0433100\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_servo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_servo/ to MongoDB with id 67427c00b98d7a37c0433101\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_runtime/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_runtime/ to MongoDB with id 67427c00b98d7a37c0433102\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_warehouse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_warehouse/ to MongoDB with id 67427c01b98d7a37c0433103\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_visualization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_visualization/ to MongoDB with id 67427c01b98d7a37c0433104\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_trajectory_cache/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_trajectory_cache/ to MongoDB with id 67427c02b98d7a37c0433105\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_tests/ to MongoDB with id 67427c02b98d7a37c0433106\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_robot_interaction/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_robot_interaction/ to MongoDB with id 67427c03b98d7a37c0433107\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_planning_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_planning_interface/ to MongoDB with id 67427c03b98d7a37c0433108\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_planning/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_planning/ to MongoDB with id 67427c04b98d7a37c0433109\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_perception/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_perception/ to MongoDB with id 67427c04b98d7a37c043310a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_occupancy_map_monitor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_occupancy_map_monitor/ to MongoDB with id 67427c05b98d7a37c043310b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_move_group/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_move_group/ to MongoDB with id 67427c06b98d7a37c043310c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_control_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_control_interface/ to MongoDB with id 67427c06b98d7a37c043310d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros_benchmarks/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros_benchmarks/ to MongoDB with id 67427c07b98d7a37c043310e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_ros/ to MongoDB with id 67427c07b98d7a37c043310f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_prbt_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_prbt_support/ to MongoDB with id 67427c08b98d7a37c0433110\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_prbt_pg70_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_prbt_pg70_support/ to MongoDB with id 67427c08b98d7a37c0433111\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_prbt_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_prbt_moveit_config/ to MongoDB with id 67427c09b98d7a37c0433112\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_prbt_ikfast_manipulator_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_prbt_ikfast_manipulator_plugin/ to MongoDB with id 67427c09b98d7a37c0433113\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_pr2_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_pr2_description/ to MongoDB with id 67427c0ab98d7a37c0433114\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_panda_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_panda_moveit_config/ to MongoDB with id 67427c0ab98d7a37c0433115\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_panda_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_panda_description/ to MongoDB with id 67427c0ab98d7a37c0433116\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_fanuc_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_fanuc_moveit_config/ to MongoDB with id 67427c0bb98d7a37c0433117\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources_fanuc_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources_fanuc_description/ to MongoDB with id 67427c0bb98d7a37c0433118\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_resources/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_resources/ to MongoDB with id 67427c0cb98d7a37c0433119\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_py/ to MongoDB with id 67427c0cb98d7a37c043311a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_plugins/ to MongoDB with id 67427c0db98d7a37c043311b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_planners_stomp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_planners_stomp/ to MongoDB with id 67427c0db98d7a37c043311c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_planners_ompl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_planners_ompl/ to MongoDB with id 67427c0eb98d7a37c043311d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_planners_chomp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_planners_chomp/ to MongoDB with id 67427c0eb98d7a37c043311e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_planners/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_planners/ to MongoDB with id 67427c0fb98d7a37c043311f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_msgs/ to MongoDB with id 67427c0fb98d7a37c0433120\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_kinematics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_kinematics/ to MongoDB with id 67427c10b98d7a37c0433121\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_hybrid_planning/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_hybrid_planning/ to MongoDB with id 67427c10b98d7a37c0433122\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_core/ to MongoDB with id 67427c11b98d7a37c0433123\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_configs_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_configs_utils/ to MongoDB with id 67427c11b98d7a37c0433124\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit_common/ to MongoDB with id 67427c11b98d7a37c0433125\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit2z_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit2z_client/ to MongoDB with id 67427c12b98d7a37c0433126\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/moveit/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/moveit/ to MongoDB with id 67427c13b98d7a37c0433127\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/move_group_interface_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/move_group_interface_client/ to MongoDB with id 67427c13b98d7a37c0433128\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mouse_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mouse_teleop/ to MongoDB with id 67427c14b98d7a37c0433129\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/motion_capture_tracking_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/motion_capture_tracking_interfaces/ to MongoDB with id 67427c14b98d7a37c043312a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/motion_capture_tracking/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/motion_capture_tracking/ to MongoDB with id 67427c15b98d7a37c043312b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_yaml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_yaml/ to MongoDB with id 67427c15b98d7a37c043312c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_viz/ to MongoDB with id 67427c16b98d7a37c043312d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_traj_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_traj_tools/ to MongoDB with id 67427c16b98d7a37c043312e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_test_datasets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_test_datasets/ to MongoDB with id 67427c17b98d7a37c043312f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_relocalization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_relocalization/ to MongoDB with id 67427c17b98d7a37c0433130\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_pose_list/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_pose_list/ to MongoDB with id 67427c18b98d7a37c0433131\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_navstate_fuse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_navstate_fuse/ to MongoDB with id 67427c18b98d7a37c0433132\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_navstate_fg/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_navstate_fg/ to MongoDB with id 67427c19b98d7a37c0433133\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_msgs/ to MongoDB with id 67427c19b98d7a37c0433134\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_metric_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_metric_maps/ to MongoDB with id 67427c1ab98d7a37c0433135\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_lidar_odometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_lidar_odometry/ to MongoDB with id 67427c1ab98d7a37c0433136\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_launcher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_launcher/ to MongoDB with id 67427c1bb98d7a37c0433137\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_kernel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_kernel/ to MongoDB with id 67427c1bb98d7a37c0433138\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_rosbag2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_rosbag2/ to MongoDB with id 67427c1cb98d7a37c0433139\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_ros2/ to MongoDB with id 67427c1cb98d7a37c043313a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_rawlog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_rawlog/ to MongoDB with id 67427c1db98d7a37c043313b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_paris_luco_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_paris_luco_dataset/ to MongoDB with id 67427c1db98d7a37c043313c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_mulran_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_mulran_dataset/ to MongoDB with id 67427c1fb98d7a37c043313d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_kitti_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_kitti_dataset/ to MongoDB with id 67427c1fb98d7a37c043313e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_kitti360_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_kitti360_dataset/ to MongoDB with id 67427c20b98d7a37c043313f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_input_euroc_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_input_euroc_dataset/ to MongoDB with id 67427c20b98d7a37c0433140\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_imu_preintegration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_imu_preintegration/ to MongoDB with id 67427c21b98d7a37c0433141\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_demos/ to MongoDB with id 67427c22b98d7a37c0433142\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_common/ to MongoDB with id 67427c22b98d7a37c0433143\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola_bridge_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola_bridge_ros2/ to MongoDB with id 67427c23b98d7a37c0433144\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mola/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mola/ to MongoDB with id 67427c23b98d7a37c0433145\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_robot_gt_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_robot_gt_msgs/ to MongoDB with id 67427c23b98d7a37c0433146\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_robot_gt/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_robot_gt/ to MongoDB with id 67427c24b98d7a37c0433147\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_msgs/ to MongoDB with id 67427c24b98d7a37c0433148\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_marker_viz_srvs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_marker_viz_srvs/ to MongoDB with id 67427c25b98d7a37c0433149\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_marker_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_marker_viz/ to MongoDB with id 67427c25b98d7a37c043314a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_marker_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_marker_publisher/ to MongoDB with id 67427c26b98d7a37c043314b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_dummy_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_dummy_driver/ to MongoDB with id 67427c26b98d7a37c043314c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_control_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_control_msgs/ to MongoDB with id 67427c27b98d7a37c043314d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mocap4r2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mocap4r2_control/ to MongoDB with id 67427c27b98d7a37c043314e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mobileye_560_660_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mobileye_560_660_msgs/ to MongoDB with id 67427c27b98d7a37c043314f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_robot/ to MongoDB with id 67427c28b98d7a37c0433150\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_navigation/ to MongoDB with id 67427c28b98d7a37c0433151\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_msgs/ to MongoDB with id 67427c29b98d7a37c0433152\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_gazebo/ to MongoDB with id 67427c29b98d7a37c0433153\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_dwb_critics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_dwb_critics/ to MongoDB with id 67427c2ab98d7a37c0433154\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_driver/ to MongoDB with id 67427c2ab98d7a37c0433155\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_description/ to MongoDB with id 67427c2bb98d7a37c0433156\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mir_actions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mir_actions/ to MongoDB with id 67427c2bb98d7a37c0433157\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/microstrain_inertial_rqt/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/microstrain_inertial_rqt/ to MongoDB with id 67427c2bb98d7a37c0433158\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/microstrain_inertial_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/microstrain_inertial_msgs/ to MongoDB with id 67427c2cb98d7a37c0433159\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/microstrain_inertial_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/microstrain_inertial_examples/ to MongoDB with id 67427c2db98d7a37c043315a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/microstrain_inertial_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/microstrain_inertial_driver/ to MongoDB with id 67427c2eb98d7a37c043315b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/microstrain_inertial_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/microstrain_inertial_description/ to MongoDB with id 67427c2eb98d7a37c043315c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/micro_ros_diagnostic_updater/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/micro_ros_diagnostic_updater/ to MongoDB with id 67427c2fb98d7a37c043315d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/micro_ros_diagnostic_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/micro_ros_diagnostic_bridge/ to MongoDB with id 67427c2fb98d7a37c043315e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/metro_nav_demo_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/metro_nav_demo_utils/ to MongoDB with id 67427c30b98d7a37c043315f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/metro_benchmark_pub/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/metro_benchmark_pub/ to MongoDB with id 67427c30b98d7a37c0433160\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/metro_benchmark_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/metro_benchmark_msgs/ to MongoDB with id 67427c31b98d7a37c0433161\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/metavision_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/metavision_driver/ to MongoDB with id 67427c31b98d7a37c0433162\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/message_tf_frame_transformer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/message_tf_frame_transformer/ to MongoDB with id 67427c32b98d7a37c0433163\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/message_modification/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/message_modification/ to MongoDB with id 67427c33b98d7a37c0433164\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/message_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/message_filters/ to MongoDB with id 67427c34b98d7a37c0433165\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/menge_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/menge_vendor/ to MongoDB with id 67427c34b98d7a37c0433166\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mcap_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mcap_vendor/ to MongoDB with id 67427c35b98d7a37c0433167\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mavros_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mavros_msgs/ to MongoDB with id 67427c35b98d7a37c0433168\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mavros_extras/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mavros_extras/ to MongoDB with id 67427c36b98d7a37c0433169\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mavros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mavros/ to MongoDB with id 67427c37b98d7a37c043316a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_visualization_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_visualization_msgs/ to MongoDB with id 67427c37b98d7a37c043316b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_status_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_status_msgs/ to MongoDB with id 67427c38b98d7a37c043316c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_sensor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_sensor_msgs/ to MongoDB with id 67427c38b98d7a37c043316d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_perception_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_perception_msgs/ to MongoDB with id 67427c38b98d7a37c043316e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_nav_msgs/ to MongoDB with id 67427c39b98d7a37c043316f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_introspection_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_introspection_msgs/ to MongoDB with id 67427c39b98d7a37c0433170\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_dbw_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_dbw_msgs/ to MongoDB with id 67427c3ab98d7a37c0433171\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_common_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_common_msgs/ to MongoDB with id 67427c3ab98d7a37c0433172\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/marti_can_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/marti_can_msgs/ to MongoDB with id 67427c3bb98d7a37c0433173\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mapviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mapviz_plugins/ to MongoDB with id 67427c3bb98d7a37c0433174\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mapviz_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mapviz_interfaces/ to MongoDB with id 67427c3cb98d7a37c0433175\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/mapviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/mapviz/ to MongoDB with id 67427c3cb98d7a37c0433176\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/magic_enum/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/magic_enum/ to MongoDB with id 67427c3db98d7a37c0433177\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lusb/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lusb/ to MongoDB with id 67427c3eb98d7a37c0433178\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lsc_ros2_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lsc_ros2_driver/ to MongoDB with id 67427c3eb98d7a37c0433179\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/logging_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/logging_demo/ to MongoDB with id 67427c3fb98d7a37c043317a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lms1xx/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lms1xx/ to MongoDB with id 67427c3fb98d7a37c043317b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lifecyclenode_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lifecyclenode_client/ to MongoDB with id 67427c40b98d7a37c043317c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lifecycle_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lifecycle_py/ to MongoDB with id 67427c40b98d7a37c043317d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lifecycle/ to MongoDB with id 67427c41b98d7a37c043317e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lidar_situational_graphs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lidar_situational_graphs/ to MongoDB with id 67427c42b98d7a37c043317f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libstatistics_collector/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libstatistics_collector/ to MongoDB with id 67427c42b98d7a37c0433180\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/librealsense2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/librealsense2/ to MongoDB with id 67427c43b98d7a37c0433181\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libpointmatcher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libpointmatcher/ to MongoDB with id 67427c43b98d7a37c0433182\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libnabo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libnabo/ to MongoDB with id 67427c44b98d7a37c0433183\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libmavconn/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libmavconn/ to MongoDB with id 67427c44b98d7a37c0433184\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libcurl_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libcurl_vendor/ to MongoDB with id 67427c45b98d7a37c0433185\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libcreate/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libcreate/ to MongoDB with id 67427c45b98d7a37c0433186\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libcaer_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libcaer_vendor/ to MongoDB with id 67427c46b98d7a37c0433187\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/libcaer_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/libcaer_driver/ to MongoDB with id 67427c46b98d7a37c0433188\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_teleop/ to MongoDB with id 67427c47b98d7a37c0433189\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_simulator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_simulator/ to MongoDB with id 67427c47b98d7a37c043318a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_robot/ to MongoDB with id 67427c48b98d7a37c043318b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_msgs/ to MongoDB with id 67427c48b98d7a37c043318c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_gz_worlds/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_gz_worlds/ to MongoDB with id 67427c48b98d7a37c043318d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_gz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_gz_plugins/ to MongoDB with id 67427c49b98d7a37c043318e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_gz_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_gz_bringup/ to MongoDB with id 67427c49b98d7a37c043318f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_fw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_fw/ to MongoDB with id 67427c4ab98d7a37c0433190\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_description/ to MongoDB with id 67427c4ab98d7a37c0433191\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo_bringup/ to MongoDB with id 67427c4bb98d7a37c0433192\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/leo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/leo/ to MongoDB with id 67427c4bb98d7a37c0433193\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_yaml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_yaml/ to MongoDB with id 67427c4cb98d7a37c0433194\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_xml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_xml/ to MongoDB with id 67427c4cb98d7a37c0433195\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_testing_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_testing_ros/ to MongoDB with id 67427c4db98d7a37c0433196\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_testing_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_testing_examples/ to MongoDB with id 67427c4db98d7a37c0433197\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_testing_ament_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_testing_ament_cmake/ to MongoDB with id 67427c4eb98d7a37c0433198\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_testing/ to MongoDB with id 67427c4eb98d7a37c0433199\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_ros/ to MongoDB with id 67427c4fb98d7a37c043319a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_pytest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_pytest/ to MongoDB with id 67427c4fb98d7a37c043319b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_param_builder/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_param_builder/ to MongoDB with id 67427c50b98d7a37c043319c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch_pal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch_pal/ to MongoDB with id 67427c50b98d7a37c043319d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/launch/ to MongoDB with id 67427c51b98d7a37c043319e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/laser_segmentation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/laser_segmentation/ to MongoDB with id 67427c51b98d7a37c043319f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/laser_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/laser_proc/ to MongoDB with id 67427c52b98d7a37c04331a0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/laser_geometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/laser_geometry/ to MongoDB with id 67427c52b98d7a37c04331a1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_validation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_validation/ to MongoDB with id 67427c53b98d7a37c04331a2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_traffic_rules/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_traffic_rules/ to MongoDB with id 67427c53b98d7a37c04331a3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_routing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_routing/ to MongoDB with id 67427c54b98d7a37c04331a4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_python/ to MongoDB with id 67427c54b98d7a37c04331a5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_projection/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_projection/ to MongoDB with id 67427c54b98d7a37c04331a6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_matching/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_matching/ to MongoDB with id 67427c55b98d7a37c04331a7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_maps/ to MongoDB with id 67427c55b98d7a37c04331a8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_io/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_io/ to MongoDB with id 67427c56b98d7a37c04331a9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_examples/ to MongoDB with id 67427c56b98d7a37c04331aa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2_core/ to MongoDB with id 67427c57b98d7a37c04331ab\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/lanelet2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/lanelet2/ to MongoDB with id 67427c58b98d7a37c04331ac\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_sunrise_fri_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_sunrise_fri_driver/ to MongoDB with id 67427c59b98d7a37c04331ad\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_rsi_simulator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_rsi_simulator/ to MongoDB with id 67427c5ab98d7a37c04331ae\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_robot_descriptions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_robot_descriptions/ to MongoDB with id 67427c5ab98d7a37c04331af\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_resources/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_resources/ to MongoDB with id 67427c5ab98d7a37c04331b0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_quantec_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_quantec_support/ to MongoDB with id 67427c5bb98d7a37c04331b1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_mock_hardware_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_mock_hardware_interface/ to MongoDB with id 67427c5bb98d7a37c04331b2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_lbr_iiwa_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_lbr_iiwa_support/ to MongoDB with id 67427c5cb98d7a37c04331b3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_lbr_iiwa_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_lbr_iiwa_moveit_config/ to MongoDB with id 67427c5cb98d7a37c04331b4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_lbr_iisy_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_lbr_iisy_support/ to MongoDB with id 67427c5db98d7a37c04331b5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_lbr_iisy_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_lbr_iisy_moveit_config/ to MongoDB with id 67427c5db98d7a37c04331b6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_kss_rsi_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_kss_rsi_driver/ to MongoDB with id 67427c5eb98d7a37c04331b7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_kr_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_kr_moveit_config/ to MongoDB with id 67427c5eb98d7a37c04331b8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_iontec_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_iontec_support/ to MongoDB with id 67427c5fb98d7a37c04331b9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_iiqka_eac_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_iiqka_eac_driver/ to MongoDB with id 67427c5fb98d7a37c04331ba\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_fortec_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_fortec_support/ to MongoDB with id 67427c5fb98d7a37c04331bb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_external_control_sdk_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_external_control_sdk_examples/ to MongoDB with id 67427c60b98d7a37c04331bc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_external_control_sdk/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_external_control_sdk/ to MongoDB with id 67427c60b98d7a37c04331bd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_event_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_event_broadcaster/ to MongoDB with id 67427c61b98d7a37c04331be\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_drivers_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_drivers_core/ to MongoDB with id 67427c62b98d7a37c04331bf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_drivers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_drivers/ to MongoDB with id 67427c62b98d7a37c04331c0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_driver_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_driver_interfaces/ to MongoDB with id 67427c63b98d7a37c04331c1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_cybertech_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_cybertech_support/ to MongoDB with id 67427c63b98d7a37c04331c2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_controllers/ to MongoDB with id 67427c63b98d7a37c04331c3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_control_mode_handler/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_control_mode_handler/ to MongoDB with id 67427c64b98d7a37c04331c4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kuka_agilus_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kuka_agilus_support/ to MongoDB with id 67427c64b98d7a37c04331c5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kortex_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kortex_driver/ to MongoDB with id 67427c65b98d7a37c04331c6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kortex_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kortex_description/ to MongoDB with id 67427c65b98d7a37c04331c7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kortex_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kortex_bringup/ to MongoDB with id 67427c66b98d7a37c04331c8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kortex_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kortex_api/ to MongoDB with id 67427c67b98d7a37c04331c9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kobuki_velocity_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kobuki_velocity_smoother/ to MongoDB with id 67427c67b98d7a37c04331ca\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kobuki_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kobuki_core/ to MongoDB with id 67427c68b98d7a37c04331cb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kitti_metrics_eval/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kitti_metrics_eval/ to MongoDB with id 67427c68b98d7a37c04331cc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kinova_gen3_lite_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kinova_gen3_lite_moveit_config/ to MongoDB with id 67427c69b98d7a37c04331cd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kinova_gen3_7dof_robotiq_2f_85_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kinova_gen3_7dof_robotiq_2f_85_moveit_config/ to MongoDB with id 67427c69b98d7a37c04331ce\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kinova_gen3_6dof_robotiq_2f_85_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kinova_gen3_6dof_robotiq_2f_85_moveit_config/ to MongoDB with id 67427c69b98d7a37c04331cf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kinematics_interface_pinocchio/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kinematics_interface_pinocchio/ to MongoDB with id 67427c6ab98d7a37c04331d0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kinematics_interface_kdl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kinematics_interface_kdl/ to MongoDB with id 67427c6ab98d7a37c04331d1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kinematics_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kinematics_interface/ to MongoDB with id 67427c6bb98d7a37c04331d2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/keyboard_handler/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/keyboard_handler/ to MongoDB with id 67427c6bb98d7a37c04331d3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/keyboard_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/keyboard_client/ to MongoDB with id 67427c6cb98d7a37c04331d4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/key_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/key_teleop/ to MongoDB with id 67427c6cb98d7a37c04331d5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kdl_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kdl_parser/ to MongoDB with id 67427c6db98d7a37c04331d6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/kartech_linear_actuator_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/kartech_linear_actuator_msgs/ to MongoDB with id 67427c6db98d7a37c04331d7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joy_tester/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joy_tester/ to MongoDB with id 67427c6eb98d7a37c04331d8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joy_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joy_teleop/ to MongoDB with id 67427c6eb98d7a37c04331d9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joy/ to MongoDB with id 67427c6fb98d7a37c04331da\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joint_trajectory_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joint_trajectory_controller/ to MongoDB with id 67427c6fb98d7a37c04331db\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joint_state_publisher_gui/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joint_state_publisher_gui/ to MongoDB with id 67427c70b98d7a37c04331dc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joint_state_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joint_state_publisher/ to MongoDB with id 67427c70b98d7a37c04331dd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joint_state_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joint_state_broadcaster/ to MongoDB with id 67427c70b98d7a37c04331de\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joint_limits/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joint_limits/ to MongoDB with id 67427c71b98d7a37c04331df\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/joint_group_impedance_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/joint_group_impedance_controller/ to MongoDB with id 67427c71b98d7a37c04331e0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/io_context/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/io_context/ to MongoDB with id 67427c72b98d7a37c04331e1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/intra_process_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/intra_process_demo/ to MongoDB with id 67427c73b98d7a37c04331e2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/interactive_markers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/interactive_markers/ to MongoDB with id 67427c73b98d7a37c04331e3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/interactive_marker_twist_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/interactive_marker_twist_server/ to MongoDB with id 67427c74b98d7a37c04331e4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/imu_transformer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/imu_transformer/ to MongoDB with id 67427c74b98d7a37c04331e5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/imu_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/imu_tools/ to MongoDB with id 67427c75b98d7a37c04331e6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/imu_sensor_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/imu_sensor_broadcaster/ to MongoDB with id 67427c75b98d7a37c04331e7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/imu_filter_madgwick/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/imu_filter_madgwick/ to MongoDB with id 67427c76b98d7a37c04331e8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/imu_complementary_filter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/imu_complementary_filter/ to MongoDB with id 67427c76b98d7a37c04331e9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_view/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_view/ to MongoDB with id 67427c77b98d7a37c04331ea\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_transport_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_transport_plugins/ to MongoDB with id 67427c77b98d7a37c04331eb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_transport/ to MongoDB with id 67427c78b98d7a37c04331ec\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_tools/ to MongoDB with id 67427c79b98d7a37c04331ed\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_rotate/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_rotate/ to MongoDB with id 67427c79b98d7a37c04331ee\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_publisher/ to MongoDB with id 67427c79b98d7a37c04331ef\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_proc/ to MongoDB with id 67427c7ab98d7a37c04331f0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_pipeline/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_pipeline/ to MongoDB with id 67427c7ab98d7a37c04331f1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/image_geometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/image_geometry/ to MongoDB with id 67427c7bb98d7a37c04331f2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/iiqka_moveit_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/iiqka_moveit_example/ to MongoDB with id 67427c7bb98d7a37c04331f3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ign_rviz_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ign_rviz_common/ to MongoDB with id 67427c7cb98d7a37c04331f4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ign_ros2_control_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ign_ros2_control_demos/ to MongoDB with id 67427c7cb98d7a37c04331f5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ign_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ign_ros2_control/ to MongoDB with id 67427c7db98d7a37c04331f6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ibeo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ibeo_msgs/ to MongoDB with id 67427c7db98d7a37c04331f7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/http_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/http_client/ to MongoDB with id 67427c7eb98d7a37c04331f8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri_rviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri_rviz/ to MongoDB with id 67427c7eb98d7a37c04331f9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri_privacy_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri_privacy_msgs/ to MongoDB with id 67427c7fb98d7a37c04331fa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri_msgs/ to MongoDB with id 67427c7fb98d7a37c04331fb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri_face_detect/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri_face_detect/ to MongoDB with id 67427c80b98d7a37c04331fc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri_face_body_matcher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri_face_body_matcher/ to MongoDB with id 67427c80b98d7a37c04331fd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri_actions_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri_actions_msgs/ to MongoDB with id 67427c81b98d7a37c04331fe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hri/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hri/ to MongoDB with id 67427c81b98d7a37c04331ff\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hpp-fcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hpp-fcl/ to MongoDB with id 67427c82b98d7a37c0433200\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/homing_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/homing_local_planner/ to MongoDB with id 67427c82b98d7a37c0433201\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hls_lfcd_lds_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hls_lfcd_lds_driver/ to MongoDB with id 67427c83b98d7a37c0433202\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hebi_cpp_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hebi_cpp_api/ to MongoDB with id 67427c84b98d7a37c0433203\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/heaphook/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/heaphook/ to MongoDB with id 67427c85b98d7a37c0433204\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hardware_interface_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hardware_interface_testing/ to MongoDB with id 67427c86b98d7a37c0433205\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/hardware_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/hardware_interface/ to MongoDB with id 67427c86b98d7a37c0433206\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gz_ros2_control_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gz_ros2_control_tests/ to MongoDB with id 67427c86b98d7a37c0433207\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gtsam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gtsam/ to MongoDB with id 67427c87b98d7a37c0433208\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gscam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gscam/ to MongoDB with id 67427c87b98d7a37c0433209\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gripper_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gripper_controllers/ to MongoDB with id 67427c88b98d7a37c043320a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_visualization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_visualization/ to MongoDB with id 67427c88b98d7a37c043320b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_sdf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_sdf/ to MongoDB with id 67427c89b98d7a37c043320c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_rviz_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_rviz_plugin/ to MongoDB with id 67427c89b98d7a37c043320d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_ros/ to MongoDB with id 67427c8ab98d7a37c043320e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_pcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_pcl/ to MongoDB with id 67427c8bb98d7a37c043320f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_octomap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_octomap/ to MongoDB with id 67427c8bb98d7a37c0433210\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_msgs/ to MongoDB with id 67427c8bb98d7a37c0433211\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_loader/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_loader/ to MongoDB with id 67427c8cb98d7a37c0433212\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_filters/ to MongoDB with id 67427c8cb98d7a37c0433213\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_demos/ to MongoDB with id 67427c8db98d7a37c0433214\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_cv/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_cv/ to MongoDB with id 67427c8db98d7a37c0433215\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_costmap_2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_costmap_2d/ to MongoDB with id 67427c8eb98d7a37c0433216\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_core/ to MongoDB with id 67427c8eb98d7a37c0433217\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map_cmake_helpers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map_cmake_helpers/ to MongoDB with id 67427c8fb98d7a37c0433218\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grid_map/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grid_map/ to MongoDB with id 67427c8fb98d7a37c0433219\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grbl_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grbl_ros/ to MongoDB with id 67427c90b98d7a37c043321a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/grasping_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/grasping_msgs/ to MongoDB with id 67427c90b98d7a37c043321b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gpsd_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gpsd_client/ to MongoDB with id 67427c90b98d7a37c043321c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gps_umd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gps_umd/ to MongoDB with id 67427c91b98d7a37c043321d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gps_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gps_tools/ to MongoDB with id 67427c91b98d7a37c043321e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gps_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gps_msgs/ to MongoDB with id 67427c92b98d7a37c043321f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/geometry_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/geometry_tutorials/ to MongoDB with id 67427c92b98d7a37c0433220\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/geometry_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/geometry_msgs/ to MongoDB with id 67427c93b98d7a37c0433221\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/geometry2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/geometry2/ to MongoDB with id 67427c93b98d7a37c0433222\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/geometric_shapes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/geometric_shapes/ to MongoDB with id 67427c94b98d7a37c0433223\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/generate_parameter_module_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/generate_parameter_module_example/ to MongoDB with id 67427c94b98d7a37c0433224\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/generate_parameter_library_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/generate_parameter_library_py/ to MongoDB with id 67427c95b98d7a37c0433225\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/generate_parameter_library_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/generate_parameter_library_example/ to MongoDB with id 67427c95b98d7a37c0433226\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/generate_parameter_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/generate_parameter_library/ to MongoDB with id 67427c96b98d7a37c0433227\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gc_spl_2022/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gc_spl_2022/ to MongoDB with id 67427c96b98d7a37c0433228\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gc_spl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gc_spl/ to MongoDB with id 67427c97b98d7a37c0433229\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_video_monitor_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_video_monitor_utils/ to MongoDB with id 67427c97b98d7a37c043322a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_tf_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_tf_publisher/ to MongoDB with id 67427c98b98d7a37c043322b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_static_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_static_camera/ to MongoDB with id 67427c98b98d7a37c043322c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_ros_pkgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_ros_pkgs/ to MongoDB with id 67427c98b98d7a37c043322d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_ros2_control_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_ros2_control_demos/ to MongoDB with id 67427c99b98d7a37c043322e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_ros2_control/ to MongoDB with id 67427c99b98d7a37c043322f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_ros/ to MongoDB with id 67427c9ab98d7a37c0433230\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_msgs/ to MongoDB with id 67427c9bb98d7a37c0433231\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/gazebo_dev/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/gazebo_dev/ to MongoDB with id 67427c9cb98d7a37c0433232\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/game_controller_spl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/game_controller_spl/ to MongoDB with id 67427c9cb98d7a37c0433233\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/fri_state_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/fri_state_broadcaster/ to MongoDB with id 67427c9cb98d7a37c0433234\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/fri_configuration_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/fri_configuration_controller/ to MongoDB with id 67427c9db98d7a37c0433235\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/franka_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/franka_description/ to MongoDB with id 67427c9db98d7a37c0433236\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/foxglove_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/foxglove_msgs/ to MongoDB with id 67427c9eb98d7a37c0433237\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/foxglove_compressed_video_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/foxglove_compressed_video_transport/ to MongoDB with id 67427c9eb98d7a37c0433238\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/forward_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/forward_local_planner/ to MongoDB with id 67427c9fb98d7a37c0433239\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/forward_global_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/forward_global_planner/ to MongoDB with id 67427c9fb98d7a37c043323a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/forward_command_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/forward_command_controller/ to MongoDB with id 67427ca0b98d7a37c043323b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/force_torque_sensor_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/force_torque_sensor_broadcaster/ to MongoDB with id 67427ca0b98d7a37c043323c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/fmi_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/fmi_adapter/ to MongoDB with id 67427ca1b98d7a37c043323d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flir_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flir_camera_msgs/ to MongoDB with id 67427ca2b98d7a37c043323e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flir_camera_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flir_camera_description/ to MongoDB with id 67427ca2b98d7a37c043323f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_widget/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_widget/ to MongoDB with id 67427ca3b98d7a37c0433240\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_testing/ to MongoDB with id 67427ca3b98d7a37c0433241\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_states/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_states/ to MongoDB with id 67427ca3b98d7a37c0433242\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_onboard/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_onboard/ to MongoDB with id 67427ca4b98d7a37c0433243\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_msgs/ to MongoDB with id 67427ca4b98d7a37c0433244\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_mirror/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_mirror/ to MongoDB with id 67427ca5b98d7a37c0433245\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_input/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_input/ to MongoDB with id 67427ca5b98d7a37c0433246\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_core/ to MongoDB with id 67427ca6b98d7a37c0433247\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flexbe_behavior_engine/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flexbe_behavior_engine/ to MongoDB with id 67427ca6b98d7a37c0433248\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/flex_sync/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/flex_sync/ to MongoDB with id 67427ca7b98d7a37c0433249\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/find_object_2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/find_object_2d/ to MongoDB with id 67427ca7b98d7a37c043324a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/filters/ to MongoDB with id 67427ca8b98d7a37c043324b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/fields2cover/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/fields2cover/ to MongoDB with id 67427ca9b98d7a37c043324c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ffmpeg_encoder_decoder/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ffmpeg_encoder_decoder/ to MongoDB with id 67427ca9b98d7a37c043324d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/fast_gicp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/fast_gicp/ to MongoDB with id 67427caab98d7a37c043324e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/fadecandy_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/fadecandy_msgs/ to MongoDB with id 67427caab98d7a37c043324f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/extrinsic_calibrator_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/extrinsic_calibrator_examples/ to MongoDB with id 67427cabb98d7a37c0433250\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/extrinsic_calibrator_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/extrinsic_calibrator_core/ to MongoDB with id 67427cabb98d7a37c0433251\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/extrinsic_calibrator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/extrinsic_calibrator/ to MongoDB with id 67427cacb98d7a37c0433252\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/executive_smach/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/executive_smach/ to MongoDB with id 67427cacb98d7a37c0433253\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_tf2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_tf2_py/ to MongoDB with id 67427cadb98d7a37c0433254\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_pointcloud_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_pointcloud_publisher/ to MongoDB with id 67427cadb98d7a37c0433255\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_minimal_subscriber/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_minimal_subscriber/ to MongoDB with id 67427caeb98d7a37c0433256\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_minimal_service/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_minimal_service/ to MongoDB with id 67427caeb98d7a37c0433257\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_minimal_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_minimal_publisher/ to MongoDB with id 67427cafb98d7a37c0433258\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_minimal_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_minimal_client/ to MongoDB with id 67427cafb98d7a37c0433259\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_minimal_action_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_minimal_action_server/ to MongoDB with id 67427cafb98d7a37c043325a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_minimal_action_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_minimal_action_client/ to MongoDB with id 67427cb0b98d7a37c043325b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_guard_conditions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_guard_conditions/ to MongoDB with id 67427cb0b98d7a37c043325c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclpy_executors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclpy_executors/ to MongoDB with id 67427cb1b98d7a37c043325d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_wait_set/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_wait_set/ to MongoDB with id 67427cb1b98d7a37c043325e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_multithreaded_executor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_multithreaded_executor/ to MongoDB with id 67427cb2b98d7a37c043325f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_timer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_timer/ to MongoDB with id 67427cb2b98d7a37c0433260\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_subscriber/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_subscriber/ to MongoDB with id 67427cb3b98d7a37c0433261\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_service/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_service/ to MongoDB with id 67427cb3b98d7a37c0433262\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_publisher/ to MongoDB with id 67427cb3b98d7a37c0433263\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_composition/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_composition/ to MongoDB with id 67427cb4b98d7a37c0433264\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_client/ to MongoDB with id 67427cb4b98d7a37c0433265\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_action_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_action_server/ to MongoDB with id 67427cb5b98d7a37c0433266\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_action_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_minimal_action_client/ to MongoDB with id 67427cb5b98d7a37c0433267\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_cbg_executor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_cbg_executor/ to MongoDB with id 67427cb6b98d7a37c0433268\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/examples_rclcpp_async_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/examples_rclcpp_async_client/ to MongoDB with id 67427cb6b98d7a37c0433269\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/example_simulation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/example_simulation/ to MongoDB with id 67427cb7b98d7a37c043326a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/example_scenario_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/example_scenario_control/ to MongoDB with id 67427cb7b98d7a37c043326b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/example_multi_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/example_multi_robot/ to MongoDB with id 67427cb8b98d7a37c043326c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/event_camera_renderer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/event_camera_renderer/ to MongoDB with id 67427cb8b98d7a37c043326d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/event_camera_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/event_camera_py/ to MongoDB with id 67427cb8b98d7a37c043326e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/event_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/event_camera_msgs/ to MongoDB with id 67427cb9b98d7a37c043326f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/event_camera_codecs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/event_camera_codecs/ to MongoDB with id 67427cb9b98d7a37c0433270\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_vam_ts_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_vam_ts_msgs/ to MongoDB with id 67427cbab98d7a37c0433271\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_vam_ts_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_vam_ts_conversion/ to MongoDB with id 67427cbab98d7a37c0433272\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_vam_ts_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_vam_ts_coding/ to MongoDB with id 67427cbbb98d7a37c0433273\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_rviz_plugins/ to MongoDB with id 67427cbbb98d7a37c0433274\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_primitives_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_primitives_conversion/ to MongoDB with id 67427cbcb98d7a37c0433275\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_msgs_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_msgs_utils/ to MongoDB with id 67427cbcb98d7a37c0433276\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_msgs/ to MongoDB with id 67427cbdb98d7a37c0433277\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_messages/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_messages/ to MongoDB with id 67427cbdb98d7a37c0433278\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_denm_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_denm_msgs/ to MongoDB with id 67427cbeb98d7a37c0433279\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_denm_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_denm_conversion/ to MongoDB with id 67427cbeb98d7a37c043327a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_denm_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_denm_coding/ to MongoDB with id 67427cbeb98d7a37c043327b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cpm_ts_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cpm_ts_msgs/ to MongoDB with id 67427cbfb98d7a37c043327c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cpm_ts_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cpm_ts_conversion/ to MongoDB with id 67427cbfb98d7a37c043327d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cpm_ts_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cpm_ts_coding/ to MongoDB with id 67427cc0b98d7a37c043327e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_conversion/ to MongoDB with id 67427cc0b98d7a37c043327f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_coding/ to MongoDB with id 67427cc1b98d7a37c0433280\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cam_ts_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cam_ts_msgs/ to MongoDB with id 67427cc1b98d7a37c0433281\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cam_ts_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cam_ts_conversion/ to MongoDB with id 67427cc2b98d7a37c0433282\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cam_ts_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cam_ts_coding/ to MongoDB with id 67427cc2b98d7a37c0433283\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cam_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cam_msgs/ to MongoDB with id 67427cc3b98d7a37c0433284\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cam_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cam_conversion/ to MongoDB with id 67427cc3b98d7a37c0433285\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/etsi_its_cam_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/etsi_its_cam_coding/ to MongoDB with id 67427cc3b98d7a37c0433286\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ess_imu_driver2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ess_imu_driver2/ to MongoDB with id 67427cc4b98d7a37c0433287\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/eigenpy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/eigenpy/ to MongoDB with id 67427cc5b98d7a37c0433288\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/eigen_stl_containers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/eigen_stl_containers/ to MongoDB with id 67427cc5b98d7a37c0433289\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/eg_random_generator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/eg_random_generator/ to MongoDB with id 67427cc6b98d7a37c043328a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/eg_conditional_generator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/eg_conditional_generator/ to MongoDB with id 67427cc6b98d7a37c043328b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/effort_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/effort_controllers/ to MongoDB with id 67427cc7b98d7a37c043328c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_utilities/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_utilities/ to MongoDB with id 67427cc7b98d7a37c043328d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_type_traits/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_type_traits/ to MongoDB with id 67427cc8b98d7a37c043328e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_time_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_time_lite/ to MongoDB with id 67427cc8b98d7a37c043328f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_time/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_time/ to MongoDB with id 67427cc9b98d7a37c0433290\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_threads/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_threads/ to MongoDB with id 67427cc9b98d7a37c0433291\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_streams/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_streams/ to MongoDB with id 67427ccab98d7a37c0433292\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_statistics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_statistics/ to MongoDB with id 67427ccab98d7a37c0433293\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_sigslots_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_sigslots_lite/ to MongoDB with id 67427ccbb98d7a37c0433294\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_sigslots/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_sigslots/ to MongoDB with id 67427ccbb98d7a37c0433295\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_mpl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_mpl/ to MongoDB with id 67427cccb98d7a37c0433296\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_mobile_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_mobile_robot/ to MongoDB with id 67427cccb98d7a37c0433297\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_math/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_math/ to MongoDB with id 67427ccdb98d7a37c0433298\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_lite/ to MongoDB with id 67427ccdb98d7a37c0433299\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_linear_algebra/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_linear_algebra/ to MongoDB with id 67427cceb98d7a37c043329a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_ipc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_ipc/ to MongoDB with id 67427cceb98d7a37c043329b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_io/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_io/ to MongoDB with id 67427cceb98d7a37c043329c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_formatters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_formatters/ to MongoDB with id 67427ccfb98d7a37c043329d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_filesystem/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_filesystem/ to MongoDB with id 67427ccfb98d7a37c043329e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_exceptions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_exceptions/ to MongoDB with id 67427cd0b98d7a37c043329f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_errors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_errors/ to MongoDB with id 67427cd0b98d7a37c04332a0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_eigen/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_eigen/ to MongoDB with id 67427cd1b98d7a37c04332a1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_devices/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_devices/ to MongoDB with id 67427cd1b98d7a37c04332a2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_core_apps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_core_apps/ to MongoDB with id 67427cd2b98d7a37c04332a3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_core/ to MongoDB with id 67427cd2b98d7a37c04332a4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_converters_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_converters_lite/ to MongoDB with id 67427cd2b98d7a37c04332a5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_console/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_console/ to MongoDB with id 67427cd3b98d7a37c04332a6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_config/ to MongoDB with id 67427cd3b98d7a37c04332a7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_concepts/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_concepts/ to MongoDB with id 67427cd4b98d7a37c04332a8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecl_command_line/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecl_command_line/ to MongoDB with id 67427cd4b98d7a37c04332a9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ecal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ecal/ to MongoDB with id 67427cd5b98d7a37c04332aa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dynamixel_workbench_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dynamixel_workbench_toolbox/ to MongoDB with id 67427cd6b98d7a37c04332ab\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dynamixel_sdk_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dynamixel_sdk_examples/ to MongoDB with id 67427cd6b98d7a37c04332ac\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dynamixel_sdk/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dynamixel_sdk/ to MongoDB with id 67427cd7b98d7a37c04332ad\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dynamixel_hardware/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dynamixel_hardware/ to MongoDB with id 67427cd7b98d7a37c04332ae\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dynamic_edt_3d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dynamic_edt_3d/ to MongoDB with id 67427cd8b98d7a37c04332af\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dwb_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dwb_plugins/ to MongoDB with id 67427cd8b98d7a37c04332b0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dwb_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dwb_msgs/ to MongoDB with id 67427cd9b98d7a37c04332b1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dwb_critics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dwb_critics/ to MongoDB with id 67427cd9b98d7a37c04332b2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dwb_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dwb_core/ to MongoDB with id 67427cd9b98d7a37c04332b3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dummy_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dummy_sensors/ to MongoDB with id 67427cdab98d7a37c04332b4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dummy_robot_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dummy_robot_bringup/ to MongoDB with id 67427cdab98d7a37c04332b5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dummy_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dummy_map_server/ to MongoDB with id 67427cdbb98d7a37c04332b6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dual_laser_merger/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dual_laser_merger/ to MongoDB with id 67427cdcb98d7a37c04332b7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dual_arm_panda_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dual_arm_panda_moveit_config/ to MongoDB with id 67427cdcb98d7a37c04332b8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ds_dbw_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ds_dbw_msgs/ to MongoDB with id 67427cddb98d7a37c04332b9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ds_dbw_joystick_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ds_dbw_joystick_demo/ to MongoDB with id 67427cddb98d7a37c04332ba\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ds_dbw_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ds_dbw_can/ to MongoDB with id 67427cdeb98d7a37c04332bb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ds_dbw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ds_dbw/ to MongoDB with id 67427cdeb98d7a37c04332bc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/draco_point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/draco_point_cloud_transport/ to MongoDB with id 67427cdfb98d7a37c04332bd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/domain_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/domain_bridge/ to MongoDB with id 67427cdfb98d7a37c04332be\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/diff_drive_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/diff_drive_controller/ to MongoDB with id 67427ce0b98d7a37c04332bf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/diagnostics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/diagnostics/ to MongoDB with id 67427ce0b98d7a37c04332c0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/diagnostic_updater/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/diagnostic_updater/ to MongoDB with id 67427ce1b98d7a37c04332c1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/diagnostic_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/diagnostic_msgs/ to MongoDB with id 67427ce1b98d7a37c04332c2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/diagnostic_common_diagnostics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/diagnostic_common_diagnostics/ to MongoDB with id 67427ce2b98d7a37c04332c3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/diagnostic_aggregator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/diagnostic_aggregator/ to MongoDB with id 67427ce3b98d7a37c04332c4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/derived_object_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/derived_object_msgs/ to MongoDB with id 67427ce3b98d7a37c04332c5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthimage_to_laserscan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthimage_to_laserscan/ to MongoDB with id 67427ce3b98d7a37c04332c6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai_ros_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai_ros_msgs/ to MongoDB with id 67427ce4b98d7a37c04332c7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai_ros_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai_ros_driver/ to MongoDB with id 67427ce4b98d7a37c04332c8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai_filters/ to MongoDB with id 67427ce5b98d7a37c04332c9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai_examples/ to MongoDB with id 67427ce5b98d7a37c04332ca\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai_descriptions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai_descriptions/ to MongoDB with id 67427ce6b98d7a37c04332cb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai_bridge/ to MongoDB with id 67427ce6b98d7a37c04332cc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai/ to MongoDB with id 67427ce7b98d7a37c04332cd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depthai-ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depthai-ros/ to MongoDB with id 67427ce7b98d7a37c04332ce\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/depth_image_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/depth_image_proc/ to MongoDB with id 67427ce8b98d7a37c04332cf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/demo_nodes_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/demo_nodes_py/ to MongoDB with id 67427ce8b98d7a37c04332d0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/demo_nodes_cpp_native/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/demo_nodes_cpp_native/ to MongoDB with id 67427ce9b98d7a37c04332d1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/demo_nodes_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/demo_nodes_cpp/ to MongoDB with id 67427ce9b98d7a37c04332d2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/delphi_srr_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/delphi_srr_msgs/ to MongoDB with id 67427ceab98d7a37c04332d3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/delphi_mrr_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/delphi_mrr_msgs/ to MongoDB with id 67427ceab98d7a37c04332d4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/delphi_esr_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/delphi_esr_msgs/ to MongoDB with id 67427ceab98d7a37c04332d5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_polaris_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_polaris_msgs/ to MongoDB with id 67427cebb98d7a37c04332d6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_polaris_joystick_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_polaris_joystick_demo/ to MongoDB with id 67427cebb98d7a37c04332d7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_polaris_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_polaris_description/ to MongoDB with id 67427cecb98d7a37c04332d8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_polaris_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_polaris_can/ to MongoDB with id 67427cedb98d7a37c04332d9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_polaris/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_polaris/ to MongoDB with id 67427cedb98d7a37c04332da\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_ford_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_ford_msgs/ to MongoDB with id 67427ceeb98d7a37c04332db\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_ford_joystick_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_ford_joystick_demo/ to MongoDB with id 67427ceeb98d7a37c04332dc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_ford_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_ford_description/ to MongoDB with id 67427cefb98d7a37c04332dd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_ford_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_ford_can/ to MongoDB with id 67427cefb98d7a37c04332de\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_ford/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_ford/ to MongoDB with id 67427cf0b98d7a37c04332df\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_fca_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_fca_msgs/ to MongoDB with id 67427cf0b98d7a37c04332e0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_fca_joystick_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_fca_joystick_demo/ to MongoDB with id 67427cf1b98d7a37c04332e1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_fca_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_fca_description/ to MongoDB with id 67427cf1b98d7a37c04332e2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_fca_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_fca_can/ to MongoDB with id 67427cf2b98d7a37c04332e3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dbw_fca/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dbw_fca/ to MongoDB with id 67427cf2b98d7a37c04332e4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_ulc_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_ulc_msgs/ to MongoDB with id 67427cf2b98d7a37c04332e5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_ulc_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_ulc_can/ to MongoDB with id 67427cf3b98d7a37c04332e6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_ulc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_ulc/ to MongoDB with id 67427cf3b98d7a37c04332e7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_dbw_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_dbw_common/ to MongoDB with id 67427cf4b98d7a37c04332e8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_can_usb/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_can_usb/ to MongoDB with id 67427cf4b98d7a37c04332e9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_can_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_can_tools/ to MongoDB with id 67427cf5b98d7a37c04332ea\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_can_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_can_msgs/ to MongoDB with id 67427cf5b98d7a37c04332eb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_can_msg_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_can_msg_filters/ to MongoDB with id 67427cf6b98d7a37c04332ec\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/dataspeed_can/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/dataspeed_can/ to MongoDB with id 67427cf6b98d7a37c04332ed\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/data_tamer_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/data_tamer_msgs/ to MongoDB with id 67427cf7b98d7a37c04332ee\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/data_tamer_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/data_tamer_cpp/ to MongoDB with id 67427cf7b98d7a37c04332ef\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/create_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/create_driver/ to MongoDB with id 67427cf8b98d7a37c04332f0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/crane_plus_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/crane_plus_control/ to MongoDB with id 67427cf8b98d7a37c04332f1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/costmap_queue/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/costmap_queue/ to MongoDB with id 67427cf9b98d7a37c04332f2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/controller_manager_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/controller_manager_msgs/ to MongoDB with id 67427cf9b98d7a37c04332f3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/controller_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/controller_manager/ to MongoDB with id 67427cfab98d7a37c04332f4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/controller_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/controller_interface/ to MongoDB with id 67427cfab98d7a37c04332f5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/control_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/control_toolbox/ to MongoDB with id 67427cfbb98d7a37c04332f6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/control_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/control_msgs/ to MongoDB with id 67427cfbb98d7a37c04332f7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/compressed_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/compressed_image_transport/ to MongoDB with id 67427cfcb98d7a37c04332f8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/compressed_depth_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/compressed_depth_image_transport/ to MongoDB with id 67427cfcb98d7a37c04332f9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/composition/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/composition/ to MongoDB with id 67427cfdb98d7a37c04332fa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/common_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/common_interfaces/ to MongoDB with id 67427cfdb98d7a37c04332fb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/color_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/color_util/ to MongoDB with id 67427cfdb98d7a37c04332fc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/color_names/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/color_names/ to MongoDB with id 67427cfeb98d7a37c04332fd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/collision_log_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/collision_log_msgs/ to MongoDB with id 67427cfeb98d7a37c04332fe\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cob_srvs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cob_srvs/ to MongoDB with id 67427cffb98d7a37c04332ff\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cob_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cob_msgs/ to MongoDB with id 67427cffb98d7a37c0433300\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cob_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cob_common/ to MongoDB with id 67427d00b98d7a37c0433301\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cob_actions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cob_actions/ to MongoDB with id 67427d00b98d7a37c0433302\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/coal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/coal/ to MongoDB with id 67427d01b98d7a37c0433303\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cmake_generate_parameter_module_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cmake_generate_parameter_module_example/ to MongoDB with id 67427d01b98d7a37c0433304\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_viz/ to MongoDB with id 67427d02b98d7a37c0433305\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_socketcan_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_socketcan_interface/ to MongoDB with id 67427d02b98d7a37c0433306\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_simulator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_simulator/ to MongoDB with id 67427d03b98d7a37c0433307\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_sensors_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_sensors_description/ to MongoDB with id 67427d03b98d7a37c0433308\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_ros2_socketcan_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_ros2_socketcan_interface/ to MongoDB with id 67427d03b98d7a37c0433309\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_platform_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_platform_msgs/ to MongoDB with id 67427d04b98d7a37c043330a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_platform_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_platform_description/ to MongoDB with id 67427d04b98d7a37c043330b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_platform/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_platform/ to MongoDB with id 67427d05b98d7a37c043330c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_msgs/ to MongoDB with id 67427d05b98d7a37c043330d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_mounts_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_mounts_description/ to MongoDB with id 67427d06b98d7a37c043330e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_manipulators_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_manipulators_description/ to MongoDB with id 67427d06b98d7a37c043330f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_manipulators/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_manipulators/ to MongoDB with id 67427d06b98d7a37c0433310\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_gz/ to MongoDB with id 67427d07b98d7a37c0433311\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_generator_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_generator_gz/ to MongoDB with id 67427d07b98d7a37c0433312\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_generator_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_generator_common/ to MongoDB with id 67427d08b98d7a37c0433313\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_desktop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_desktop/ to MongoDB with id 67427d08b98d7a37c0433314\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_description/ to MongoDB with id 67427d08b98d7a37c0433315\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_customization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_customization/ to MongoDB with id 67427d09b98d7a37c0433316\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_control/ to MongoDB with id 67427d09b98d7a37c0433317\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_config_live/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_config_live/ to MongoDB with id 67427d0ab98d7a37c0433318\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_config/ to MongoDB with id 67427d0ab98d7a37c0433319\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/clearpath_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/clearpath_common/ to MongoDB with id 67427d0bb98d7a37c043331a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/classic_bags/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/classic_bags/ to MongoDB with id 67427d0bb98d7a37c043331b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/class_loader/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/class_loader/ to MongoDB with id 67427d0cb98d7a37c043331c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/chomp_motion_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/chomp_motion_planner/ to MongoDB with id 67427d0db98d7a37c043331d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/catch_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/catch_ros2/ to MongoDB with id 67427d0db98d7a37c043331e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cartographer_rviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cartographer_rviz/ to MongoDB with id 67427d0eb98d7a37c043331f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/cartographer_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/cartographer_ros/ to MongoDB with id 67427d0fb98d7a37c0433320\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/caret_trace/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/caret_trace/ to MongoDB with id 67427d0fb98d7a37c0433321\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/caret_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/caret_msgs/ to MongoDB with id 67427d10b98d7a37c0433322\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/caret_analyze_cpp_impl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/caret_analyze_cpp_impl/ to MongoDB with id 67427d10b98d7a37c0433323\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/caret_analyze/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/caret_analyze/ to MongoDB with id 67427d11b98d7a37c0433324\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/canopen_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/canopen_utils/ to MongoDB with id 67427d11b98d7a37c0433325\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/canopen_ros2_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/canopen_ros2_controllers/ to MongoDB with id 67427d12b98d7a37c0433326\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/canopen_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/canopen_ros2_control/ to MongoDB with id 67427d12b98d7a37c0433327\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/canopen_proxy_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/canopen_proxy_driver/ to MongoDB with id 67427d13b98d7a37c0433328\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/canopen_fake_slaves/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/canopen_fake_slaves/ to MongoDB with id 67427d13b98d7a37c0433329\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/canopen_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/canopen_core/ to MongoDB with id 67427d14b98d7a37c043332a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/camera_calibration_parsers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/camera_calibration_parsers/ to MongoDB with id 67427d14b98d7a37c043332b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/camera_aravis2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/camera_aravis2_msgs/ to MongoDB with id 67427d15b98d7a37c043332c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/camera_aravis2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/camera_aravis2/ to MongoDB with id 67427d15b98d7a37c043332d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bosch_locator_bridge_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bosch_locator_bridge_utils/ to MongoDB with id 67427d16b98d7a37c043332e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bosch_locator_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bosch_locator_bridge/ to MongoDB with id 67427d16b98d7a37c043332f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/boost_geometry_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/boost_geometry_util/ to MongoDB with id 67427d17b98d7a37c0433330\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bondpy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bondpy/ to MongoDB with id 67427d17b98d7a37c0433331\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bondcpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bondcpp/ to MongoDB with id 67427d18b98d7a37c0433332\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bond_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bond_core/ to MongoDB with id 67427d18b98d7a37c0433333\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bond/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bond/ to MongoDB with id 67427d19b98d7a37c0433334\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bno055/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bno055/ to MongoDB with id 67427d19b98d7a37c0433335\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bicycle_steering_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bicycle_steering_controller/ to MongoDB with id 67427d1ab98d7a37c0433336\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_tutorial/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_tutorial/ to MongoDB with id 67427d1ab98d7a37c0433337\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_tools/ to MongoDB with id 67427d1bb98d7a37c0433338\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_system_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_system_tests/ to MongoDB with id 67427d1bb98d7a37c0433339\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_ros/ to MongoDB with id 67427d1cb98d7a37c043333a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_example/ to MongoDB with id 67427d1cb98d7a37c043333b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_benchmark/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_benchmark/ to MongoDB with id 67427d1cb98d7a37c043333c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga_amcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga_amcl/ to MongoDB with id 67427d1db98d7a37c043333d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/beluga/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/beluga/ to MongoDB with id 67427d1eb98d7a37c043333e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/behaviortree_cpp_v3/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/behaviortree_cpp_v3/ to MongoDB with id 67427d1eb98d7a37c043333f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/behaviortree_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/behaviortree_cpp/ to MongoDB with id 67427d1fb98d7a37c0433340\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bcr_bot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bcr_bot/ to MongoDB with id 67427d1fb98d7a37c0433341\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/bag2_to_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/bag2_to_image/ to MongoDB with id 67427d20b98d7a37c0433342\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/backward_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/backward_ros/ to MongoDB with id 67427d20b98d7a37c0433343\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/backward_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/backward_local_planner/ to MongoDB with id 67427d21b98d7a37c0433344\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/backward_global_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/backward_global_planner/ to MongoDB with id 67427d21b98d7a37c0433345\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_vehicle_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_vehicle_msgs/ to MongoDB with id 67427d22b98d7a37c0433346\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_v2x_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_v2x_msgs/ to MongoDB with id 67427d22b98d7a37c0433347\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_system_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_system_msgs/ to MongoDB with id 67427d22b98d7a37c0433348\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_sensing_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_sensing_msgs/ to MongoDB with id 67427d23b98d7a37c0433349\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_planning_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_planning_msgs/ to MongoDB with id 67427d23b98d7a37c043334a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_perception_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_perception_msgs/ to MongoDB with id 67427d24b98d7a37c043334b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_map_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_map_msgs/ to MongoDB with id 67427d24b98d7a37c043334c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_localization_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_localization_msgs/ to MongoDB with id 67427d25b98d7a37c043334d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_control_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_control_msgs/ to MongoDB with id 67427d25b98d7a37c043334e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/autoware_common_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/autoware_common_msgs/ to MongoDB with id 67427d26b98d7a37c043334f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/automatika_ros_sugar/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/automatika_ros_sugar/ to MongoDB with id 67427d26b98d7a37c0433350\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/async_web_server_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/async_web_server_cpp/ to MongoDB with id 67427d27b98d7a37c0433351\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_visualization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_visualization/ to MongoDB with id 67427d27b98d7a37c0433352\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_usb_camera_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_usb_camera_interface/ to MongoDB with id 67427d28b98d7a37c0433353\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_state_estimator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_state_estimator/ to MongoDB with id 67427d28b98d7a37c0433354\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_rviz_plugins/ to MongoDB with id 67427d29b98d7a37c0433355\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_realsense_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_realsense_interface/ to MongoDB with id 67427d29b98d7a37c0433356\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_python_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_python_api/ to MongoDB with id 67427d2ab98d7a37c0433357\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_tello/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_tello/ to MongoDB with id 67427d2ab98d7a37c0433358\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_pixhawk/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_pixhawk/ to MongoDB with id 67427d2bb98d7a37c0433359\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_multirotor_simulator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_multirotor_simulator/ to MongoDB with id 67427d2bb98d7a37c043335a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_mavlink/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_mavlink/ to MongoDB with id 67427d2cb98d7a37c043335b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_ign_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_ign_gazebo/ to MongoDB with id 67427d2cb98d7a37c043335c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_gazebo/ to MongoDB with id 67427d2db98d7a37c043335d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_dji_psdk/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_dji_psdk/ to MongoDB with id 67427d2db98d7a37c043335e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_dji_osdk/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_dji_osdk/ to MongoDB with id 67427d2eb98d7a37c043335f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_platform_crazyflie/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_platform_crazyflie/ to MongoDB with id 67427d2eb98d7a37c0433360\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_msgs/ to MongoDB with id 67427d2fb98d7a37c0433361\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_motion_reference_handlers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_motion_reference_handlers/ to MongoDB with id 67427d2fb98d7a37c0433362\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_motion_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_motion_controller/ to MongoDB with id 67427d30b98d7a37c0433363\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_map_server/ to MongoDB with id 67427d30b98d7a37c0433364\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_keyboard_teleoperation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_keyboard_teleoperation/ to MongoDB with id 67427d31b98d7a37c0433365\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_geozones/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_geozones/ to MongoDB with id 67427d31b98d7a37c0433366\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_gazebo_classic_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_gazebo_classic_assets/ to MongoDB with id 67427d32b98d7a37c0433367\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_gazebo_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_gazebo_assets/ to MongoDB with id 67427d32b98d7a37c0433368\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_external_object_to_tf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_external_object_to_tf/ to MongoDB with id 67427d33b98d7a37c0433369\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_core/ to MongoDB with id 67427d34b98d7a37c043336a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_controller/ to MongoDB with id 67427d34b98d7a37c043336b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_cli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_cli/ to MongoDB with id 67427d35b98d7a37c043336c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behaviors_trajectory_generation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behaviors_trajectory_generation/ to MongoDB with id 67427d35b98d7a37c043336d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behaviors_platform/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behaviors_platform/ to MongoDB with id 67427d35b98d7a37c043336e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behaviors_perception/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behaviors_perception/ to MongoDB with id 67427d36b98d7a37c043336f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behaviors_path_planning/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behaviors_path_planning/ to MongoDB with id 67427d36b98d7a37c0433370\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behaviors_motion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behaviors_motion/ to MongoDB with id 67427d38b98d7a37c0433371\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behavior_tree/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behavior_tree/ to MongoDB with id 67427d39b98d7a37c0433372\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_behavior/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_behavior/ to MongoDB with id 67427d39b98d7a37c0433373\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/as2_alphanumeric_viewer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/as2_alphanumeric_viewer/ to MongoDB with id 67427d3ab98d7a37c0433374\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/aruco_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/aruco_ros/ to MongoDB with id 67427d3ab98d7a37c0433375\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/aruco_opencv_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/aruco_opencv_msgs/ to MongoDB with id 67427d3bb98d7a37c0433376\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/aruco_opencv/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/aruco_opencv/ to MongoDB with id 67427d3bb98d7a37c0433377\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/aruco/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/aruco/ to MongoDB with id 67427d3cb98d7a37c0433378\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/arm_sim_scenario/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/arm_sim_scenario/ to MongoDB with id 67427d3cb98d7a37c0433379\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apriltag_draw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apriltag_draw/ to MongoDB with id 67427d3db98d7a37c043337a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apriltag_detector_umich/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apriltag_detector_umich/ to MongoDB with id 67427d3db98d7a37c043337b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apriltag_detector_mit/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apriltag_detector_mit/ to MongoDB with id 67427d3eb98d7a37c043337c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apriltag_detector/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apriltag_detector/ to MongoDB with id 67427d3eb98d7a37c043337d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apriltag/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apriltag/ to MongoDB with id 67427d3fb98d7a37c043337e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apex_test_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apex_test_tools/ to MongoDB with id 67427d3fb98d7a37c043337f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/apex_containers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/apex_containers/ to MongoDB with id 67427d40b98d7a37c0433380\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/angles/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/angles/ to MongoDB with id 67427d41b98d7a37c0433381\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_slam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_slam/ to MongoDB with id 67427d41b98d7a37c0433382\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_navigation/ to MongoDB with id 67427d41b98d7a37c0433383\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_hardware/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_hardware/ to MongoDB with id 67427d42b98d7a37c0433384\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_gz_classic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_gz_classic/ to MongoDB with id 67427d43b98d7a37c0433385\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_gz/ to MongoDB with id 67427d43b98d7a37c0433386\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_firmware/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_firmware/ to MongoDB with id 67427d44b98d7a37c0433387\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_description/ to MongoDB with id 67427d44b98d7a37c0433388\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_control/ to MongoDB with id 67427d45b98d7a37c0433389\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_bringup/ to MongoDB with id 67427d45b98d7a37c043338a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_base/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_base/ to MongoDB with id 67427d46b98d7a37c043338b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/andino_apps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/andino_apps/ to MongoDB with id 67427d46b98d7a37c043338c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_xmllint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_xmllint/ to MongoDB with id 67427d46b98d7a37c043338d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_uncrustify/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_uncrustify/ to MongoDB with id 67427d47b98d7a37c043338e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_pyflakes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_pyflakes/ to MongoDB with id 67427d47b98d7a37c043338f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_pycodestyle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_pycodestyle/ to MongoDB with id 67427d48b98d7a37c0433390\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_pep257/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_pep257/ to MongoDB with id 67427d48b98d7a37c0433391\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_pclint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_pclint/ to MongoDB with id 67427d49b98d7a37c0433392\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_mypy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_mypy/ to MongoDB with id 67427d49b98d7a37c0433393\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_lint_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_lint_common/ to MongoDB with id 67427d49b98d7a37c0433394\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_lint_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_lint_cmake/ to MongoDB with id 67427d4ab98d7a37c0433395\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_lint_auto/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_lint_auto/ to MongoDB with id 67427d4ab98d7a37c0433396\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_lint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_lint/ to MongoDB with id 67427d4bb98d7a37c0433397\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_index_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_index_python/ to MongoDB with id 67427d4bb98d7a37c0433398\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_index_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_index_cpp/ to MongoDB with id 67427d4cb98d7a37c0433399\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_flake8/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_flake8/ to MongoDB with id 67427d4cb98d7a37c043339a\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cpplint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cpplint/ to MongoDB with id 67427d4cb98d7a37c043339b\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cppcheck/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cppcheck/ to MongoDB with id 67427d4db98d7a37c043339c\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_copyright/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_copyright/ to MongoDB with id 67427d4db98d7a37c043339d\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_xmllint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_xmllint/ to MongoDB with id 67427d4eb98d7a37c043339e\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_version/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_version/ to MongoDB with id 67427d4eb98d7a37c043339f\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_vendor_package/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_vendor_package/ to MongoDB with id 67427d4fb98d7a37c04333a0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_uncrustify/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_uncrustify/ to MongoDB with id 67427d4fb98d7a37c04333a1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_test/ to MongoDB with id 67427d50b98d7a37c04333a2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_target_dependencies/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_target_dependencies/ to MongoDB with id 67427d50b98d7a37c04333a3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_python/ to MongoDB with id 67427d51b98d7a37c04333a4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_pytest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_pytest/ to MongoDB with id 67427d51b98d7a37c04333a5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_pyflakes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_pyflakes/ to MongoDB with id 67427d51b98d7a37c04333a6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_pycodestyle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_pycodestyle/ to MongoDB with id 67427d52b98d7a37c04333a7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_pep257/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_pep257/ to MongoDB with id 67427d52b98d7a37c04333a8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_pclint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_pclint/ to MongoDB with id 67427d53b98d7a37c04333a9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_nose/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_nose/ to MongoDB with id 67427d53b98d7a37c04333aa\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_mypy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_mypy/ to MongoDB with id 67427d54b98d7a37c04333ab\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_lint_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_lint_cmake/ to MongoDB with id 67427d54b98d7a37c04333ac\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_libraries/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_libraries/ to MongoDB with id 67427d54b98d7a37c04333ad\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_include_directories/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_include_directories/ to MongoDB with id 67427d55b98d7a37c04333ae\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_gtest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_gtest/ to MongoDB with id 67427d55b98d7a37c04333af\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_google_benchmark/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_google_benchmark/ to MongoDB with id 67427d56b98d7a37c04333b0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_gmock/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_gmock/ to MongoDB with id 67427d56b98d7a37c04333b1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_gen_version_h/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_gen_version_h/ to MongoDB with id 67427d57b98d7a37c04333b2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_flake8/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_flake8/ to MongoDB with id 67427d57b98d7a37c04333b3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_targets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_targets/ to MongoDB with id 67427d58b98d7a37c04333b4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_link_flags/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_link_flags/ to MongoDB with id 67427d58b98d7a37c04333b5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_libraries/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_libraries/ to MongoDB with id 67427d59b98d7a37c04333b6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_interfaces/ to MongoDB with id 67427d59b98d7a37c04333b7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_include_directories/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_include_directories/ to MongoDB with id 67427d5ab98d7a37c04333b8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_dependencies/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_dependencies/ to MongoDB with id 67427d5ab98d7a37c04333b9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_export_definitions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_export_definitions/ to MongoDB with id 67427d5ab98d7a37c04333ba\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_cpplint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_cpplint/ to MongoDB with id 67427d5bb98d7a37c04333bb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_cppcheck/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_cppcheck/ to MongoDB with id 67427d5bb98d7a37c04333bc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_core/ to MongoDB with id 67427d5cb98d7a37c04333bd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_copyright/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_copyright/ to MongoDB with id 67427d5cb98d7a37c04333be\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_clang_tidy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_clang_tidy/ to MongoDB with id 67427d5db98d7a37c04333bf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_clang_format/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_clang_format/ to MongoDB with id 67427d5db98d7a37c04333c0\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake_auto/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake_auto/ to MongoDB with id 67427d5db98d7a37c04333c1\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_cmake/ to MongoDB with id 67427d5eb98d7a37c04333c2\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_clang_tidy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_clang_tidy/ to MongoDB with id 67427d5eb98d7a37c04333c3\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ament_clang_format/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ament_clang_format/ to MongoDB with id 67427d5fb98d7a37c04333c4\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ai_prompt_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ai_prompt_msgs/ to MongoDB with id 67427d5fb98d7a37c04333c5\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/aerostack2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/aerostack2/ to MongoDB with id 67427d60b98d7a37c04333c6\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/admittance_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/admittance_controller/ to MongoDB with id 67427d61b98d7a37c04333c7\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/adi_tmcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/adi_tmcl/ to MongoDB with id 67427d61b98d7a37c04333c8\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/adi_3dtof_image_stitching/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/adi_3dtof_image_stitching/ to MongoDB with id 67427d62b98d7a37c04333c9\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/adaptive_component/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/adaptive_component/ to MongoDB with id 67427d62b98d7a37c04333ca\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/actionlib_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/actionlib_msgs/ to MongoDB with id 67427d63b98d7a37c04333cb\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/action_tutorials_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/action_tutorials_py/ to MongoDB with id 67427d63b98d7a37c04333cc\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/action_tutorials_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/action_tutorials_interfaces/ to MongoDB with id 67427d64b98d7a37c04333cd\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/action_tutorials_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/action_tutorials_cpp/ to MongoDB with id 67427d64b98d7a37c04333ce\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/ackermann_steering_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/ackermann_steering_controller/ to MongoDB with id 67427d65b98d7a37c04333cf\n", + "\n", + "Scraping https://docs.ros.org/en/humble/p/aandd_ekew_driver_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble/p/aandd_ekew_driver_py/ to MongoDB with id 67427d65b98d7a37c04333d0\n", + "\n", + "Scraping https://docs.ros.org/en/humble#getting-started (Depth: 3)\n", + "Saved content from https://docs.ros.org/en/humble#getting-started to MongoDB with id 67427d66b98d7a37c04333d1\n", + "\n", + "Scraping https://docs.ros.org/en/humble#the-ros-2-project (Depth: 4)\n", + "Saved content from https://docs.ros.org/en/humble#the-ros-2-project to MongoDB with id 67427d67b98d7a37c04333d2\n", + "\n", + "Scraping https://docs.ros.org/en/humble#ros-community-resources (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble#ros-community-resources to MongoDB with id 67427d68b98d7a37c04333d3\n", + "Failed to access https://docs.ros.org/en/Contact.html#using-robotics-stack-exchange (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Contact.html#using-ros-discourse (Status code: 404)\n", + "\n", + "Scraping https://docs.ros.org/en/humble#general-ros-project-resources (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble#general-ros-project-resources to MongoDB with id 67427d69b98d7a37c04333d4\n", + "\n", + "Scraping https://docs.ros.org/en/humble#events (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble#events to MongoDB with id 67427d6ab98d7a37c04333d5\n", + "\n", + "Scraping https://docs.ros.org/en/humble#miscellaneous (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble#miscellaneous to MongoDB with id 67427d6bb98d7a37c04333d6\n", + "\n", + "Scraping https://docs.ros.org/en/humble#deprecated (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/humble#deprecated to MongoDB with id 67427d6bb98d7a37c04333d7\n", + "Failed to access https://docs.ros.org/iron/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/galactic/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/foxy/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/eloquent/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/dashing/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/crystal/index.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/rolling/index.html (Status code: 404)\n", + "\n", + "Scraping https://docs.ros.org/en/iron (Depth: 1)\n", + "Saved content from https://docs.ros.org/en/iron to MongoDB with id 67427d6fb98d7a37c04333d8\n", + "Failed to access https://docs.ros.org/en/Tutorials/Advanced/Improved-Dynamic-Discovery.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/Tutorials/Demos/Service-Introspection.html (Status code: 404)\n", + "Failed to access https://docs.ros.org/en/How-To-Guides/Building-ROS-2-with-Tracing.html (Status code: 404)\n", + "\n", + "Scraping https://docs.ros.org/en/iron#ros-2-documentation (Depth: 2)\n", + "Saved content from https://docs.ros.org/en/iron#ros-2-documentation to MongoDB with id 67427d71b98d7a37c04333d9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ (Depth: 3)\n", + "Saved content from https://docs.ros.org/en/iron/p/ to MongoDB with id 67427d72b98d7a37c04333da\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/?C=N;O=D (Depth: 4)\n", + "Saved content from https://docs.ros.org/en/iron/p/?C=N;O=D to MongoDB with id 67427d73b98d7a37c04333db\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/?C=N;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/?C=N;O=A to MongoDB with id 67427d74b98d7a37c04333dc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/?C=M;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/?C=M;O=A to MongoDB with id 67427d75b98d7a37c04333dd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/?C=S;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/?C=S;O=A to MongoDB with id 67427d76b98d7a37c04333de\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/?C=D;O=A (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/?C=D;O=A to MongoDB with id 67427d77b98d7a37c04333df\n", + "\n", + "Scraping https://docs.ros.org/en/iron/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/ to MongoDB with id 67427d78b98d7a37c04333e0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/zstd_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/zstd_vendor/ to MongoDB with id 67427d79b98d7a37c04333e1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/zstd_point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/zstd_point_cloud_transport/ to MongoDB with id 67427d79b98d7a37c04333e2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/zstd_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/zstd_image_transport/ to MongoDB with id 67427d7ab98d7a37c04333e3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/zlib_point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/zlib_point_cloud_transport/ to MongoDB with id 67427d7ab98d7a37c04333e4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/zbar_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/zbar_ros/ to MongoDB with id 67427d7bb98d7a37c04333e5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/xacro/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/xacro/ to MongoDB with id 67427d7bb98d7a37c04333e6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/wiimote/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/wiimote/ to MongoDB with id 67427d7cb98d7a37c04333e7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_universal_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_universal_robot/ to MongoDB with id 67427d7cb98d7a37c04333e8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_turtlebot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_turtlebot/ to MongoDB with id 67427d7db98d7a37c04333e9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_tiago/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_tiago/ to MongoDB with id 67427d7db98d7a37c04333ea\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_tests/ to MongoDB with id 67427d7db98d7a37c04333eb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_tesla/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_tesla/ to MongoDB with id 67427d7eb98d7a37c04333ec\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_msgs/ to MongoDB with id 67427d7eb98d7a37c04333ed\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_mavic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_mavic/ to MongoDB with id 67427d7fb98d7a37c04333ee\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_importer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_importer/ to MongoDB with id 67427d7fb98d7a37c04333ef\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_epuck/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_epuck/ to MongoDB with id 67427d80b98d7a37c04333f0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_driver/ to MongoDB with id 67427d80b98d7a37c04333f1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2_control/ to MongoDB with id 67427d81b98d7a37c04333f2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/webots_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/webots_ros2/ to MongoDB with id 67427d81b98d7a37c04333f3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/web_video_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/web_video_server/ to MongoDB with id 67427d82b98d7a37c04333f4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/warehouse_ros_sqlite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/warehouse_ros_sqlite/ to MongoDB with id 67427d82b98d7a37c04333f5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/warehouse_ros_mongo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/warehouse_ros_mongo/ to MongoDB with id 67427d83b98d7a37c04333f6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/warehouse_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/warehouse_ros/ to MongoDB with id 67427d83b98d7a37c04333f7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/vrpn_mocap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/vrpn_mocap/ to MongoDB with id 67427d84b98d7a37c04333f8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/vitis_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/vitis_common/ to MongoDB with id 67427d85b98d7a37c04333f9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/visualization_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/visualization_msgs/ to MongoDB with id 67427d86b98d7a37c04333fa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/vision_msgs_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/vision_msgs_rviz_plugins/ to MongoDB with id 67427d87b98d7a37c04333fb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/vision_msgs_layers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/vision_msgs_layers/ to MongoDB with id 67427d87b98d7a37c04333fc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/vision_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/vision_msgs/ to MongoDB with id 67427d87b98d7a37c04333fd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velodyne_pointcloud/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velodyne_pointcloud/ to MongoDB with id 67427d88b98d7a37c04333fe\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velodyne_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velodyne_msgs/ to MongoDB with id 67427d88b98d7a37c04333ff\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velodyne_laserscan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velodyne_laserscan/ to MongoDB with id 67427d89b98d7a37c0433400\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velodyne_gazebo_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velodyne_gazebo_plugins/ to MongoDB with id 67427d89b98d7a37c0433401\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velodyne_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velodyne_driver/ to MongoDB with id 67427d8ab98d7a37c0433402\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velodyne/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velodyne/ to MongoDB with id 67427d8ab98d7a37c0433403\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/velocity_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/velocity_controllers/ to MongoDB with id 67427d8bb98d7a37c0433404\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/v4l2_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/v4l2_camera/ to MongoDB with id 67427d8bb98d7a37c0433405\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/usb_cam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/usb_cam/ to MongoDB with id 67427d8cb98d7a37c0433406\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/urdfdom_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/urdfdom_py/ to MongoDB with id 67427d8cb98d7a37c0433407\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/urdf_parser_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/urdf_parser_plugin/ to MongoDB with id 67427d8db98d7a37c0433408\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/urdf_launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/urdf_launch/ to MongoDB with id 67427d8db98d7a37c0433409\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/urdf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/urdf/ to MongoDB with id 67427d8eb98d7a37c043340a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_robot_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_robot_driver/ to MongoDB with id 67427d8eb98d7a37c043340b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_msgs/ to MongoDB with id 67427d8fb98d7a37c043340c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_moveit_config/ to MongoDB with id 67427d8fb98d7a37c043340d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_description/ to MongoDB with id 67427d90b98d7a37c043340e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_dashboard_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_dashboard_msgs/ to MongoDB with id 67427d90b98d7a37c043340f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_controllers/ to MongoDB with id 67427d91b98d7a37c0433410\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_client_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_client_library/ to MongoDB with id 67427d92b98d7a37c0433411\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur_calibration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur_calibration/ to MongoDB with id 67427d92b98d7a37c0433412\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ur/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ur/ to MongoDB with id 67427d93b98d7a37c0433413\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/unitree_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/unitree_ros/ to MongoDB with id 67427d93b98d7a37c0433414\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/undo_path_global_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/undo_path_global_planner/ to MongoDB with id 67427d94b98d7a37c0433415\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/udp_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/udp_msgs/ to MongoDB with id 67427d94b98d7a37c0433416\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/udp_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/udp_driver/ to MongoDB with id 67427d95b98d7a37c0433417\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_ubx_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_ubx_msgs/ to MongoDB with id 67427d96b98d7a37c0433418\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_ubx_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_ubx_interfaces/ to MongoDB with id 67427d96b98d7a37c0433419\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_serialization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_serialization/ to MongoDB with id 67427d96b98d7a37c043341a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_nav_sat_fix_hp_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_nav_sat_fix_hp_node/ to MongoDB with id 67427d97b98d7a37c043341b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_msgs/ to MongoDB with id 67427d98b98d7a37c043341c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_gps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_gps/ to MongoDB with id 67427d98b98d7a37c043341d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_dgnss_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_dgnss_node/ to MongoDB with id 67427d99b98d7a37c043341e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ublox_dgnss/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ublox_dgnss/ to MongoDB with id 67427d9ab98d7a37c043341f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/twist_stamper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/twist_stamper/ to MongoDB with id 67427d9ab98d7a37c0433420\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/twist_mux/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/twist_mux/ to MongoDB with id 67427d9ab98d7a37c0433421\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tvm_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tvm_vendor/ to MongoDB with id 67427d9bb98d7a37c0433422\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tuw_geometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tuw_geometry/ to MongoDB with id 67427d9cb98d7a37c0433423\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turtlesim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turtlesim/ to MongoDB with id 67427d9cb98d7a37c0433424\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turtlebot3_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turtlebot3_gazebo/ to MongoDB with id 67427d9db98d7a37c0433425\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turtlebot3_fake_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turtlebot3_fake_node/ to MongoDB with id 67427d9db98d7a37c0433426\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turtle_tf2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turtle_tf2_py/ to MongoDB with id 67427d9db98d7a37c0433427\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turtle_tf2_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turtle_tf2_cpp/ to MongoDB with id 67427d9eb98d7a37c0433428\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turtle_nest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turtle_nest/ to MongoDB with id 67427d9fb98d7a37c0433429\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/turbojpeg_compressed_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/turbojpeg_compressed_image_transport/ to MongoDB with id 67427d9fb98d7a37c043342a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tricycle_steering_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tricycle_steering_controller/ to MongoDB with id 67427da0b98d7a37c043342b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tricycle_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tricycle_controller/ to MongoDB with id 67427da1b98d7a37c043342c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/transmission_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/transmission_interface/ to MongoDB with id 67427da2b98d7a37c043342d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/trajectory_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/trajectory_msgs/ to MongoDB with id 67427da2b98d7a37c043342e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_trace/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_trace/ to MongoDB with id 67427da3b98d7a37c043342f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_test/ to MongoDB with id 67427da3b98d7a37c0433430\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_read/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_read/ to MongoDB with id 67427da4b98d7a37c0433431\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_launch/ to MongoDB with id 67427da4b98d7a37c0433432\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_image_pipeline/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_image_pipeline/ to MongoDB with id 67427da5b98d7a37c0433433\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_analysis/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_analysis/ to MongoDB with id 67427da5b98d7a37c0433434\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools_acceleration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools_acceleration/ to MongoDB with id 67427da6b98d7a37c0433435\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tracetools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tracetools/ to MongoDB with id 67427da6b98d7a37c0433436\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/topic_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/topic_tools/ to MongoDB with id 67427da8b98d7a37c0433437\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/topic_statistics_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/topic_statistics_demo/ to MongoDB with id 67427da8b98d7a37c0433438\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/topic_monitor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/topic_monitor/ to MongoDB with id 67427da9b98d7a37c0433439\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tlsf_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tlsf_cpp/ to MongoDB with id 67427da9b98d7a37c043343a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tlsf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tlsf/ to MongoDB with id 67427da9b98d7a37c043343b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tile_map/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tile_map/ to MongoDB with id 67427daab98d7a37c043343c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/theora_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/theora_image_transport/ to MongoDB with id 67427dabb98d7a37c043343d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf_transformations/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf_transformations/ to MongoDB with id 67427dabb98d7a37c043343e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_tools/ to MongoDB with id 67427dacb98d7a37c043343f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_sensor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_sensor_msgs/ to MongoDB with id 67427dacb98d7a37c0433440\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_ros_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_ros_py/ to MongoDB with id 67427dadb98d7a37c0433441\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_ros/ to MongoDB with id 67427dadb98d7a37c0433442\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_py/ to MongoDB with id 67427daeb98d7a37c0433443\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_msgs/ to MongoDB with id 67427daeb98d7a37c0433444\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_kdl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_kdl/ to MongoDB with id 67427dafb98d7a37c0433445\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_geometry_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_geometry_msgs/ to MongoDB with id 67427db0b98d7a37c0433446\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_eigen_kdl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_eigen_kdl/ to MongoDB with id 67427db0b98d7a37c0433447\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_eigen/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_eigen/ to MongoDB with id 67427db1b98d7a37c0433448\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_bullet/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_bullet/ to MongoDB with id 67427db1b98d7a37c0433449\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2_2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2_2d/ to MongoDB with id 67427db2b98d7a37c043344a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/tf2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/tf2/ to MongoDB with id 67427db2b98d7a37c043344b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_tracetools_launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_tracetools_launch/ to MongoDB with id 67427db3b98d7a37c043344c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_tracetools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_tracetools/ to MongoDB with id 67427db3b98d7a37c043344d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_tf2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_tf2/ to MongoDB with id 67427db4b98d7a37c043344e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_ros_gz_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_ros_gz_bridge/ to MongoDB with id 67427db4b98d7a37c043344f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_ros2trace/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_ros2trace/ to MongoDB with id 67427db4b98d7a37c0433450\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_rmw_implementation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_rmw_implementation/ to MongoDB with id 67427db5b98d7a37c0433451\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_msgs/ to MongoDB with id 67427db5b98d7a37c0433452\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_launch_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_launch_testing/ to MongoDB with id 67427db6b98d7a37c0433453\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_launch_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_launch_ros/ to MongoDB with id 67427db6b98d7a37c0433454\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/test_bond/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/test_bond/ to MongoDB with id 67427db7b98d7a37c0433455\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/teleop_twist_joy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/teleop_twist_joy/ to MongoDB with id 67427db7b98d7a37c0433456\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/teleop_tools_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/teleop_tools_msgs/ to MongoDB with id 67427db8b98d7a37c0433457\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/teleop_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/teleop_tools/ to MongoDB with id 67427db8b98d7a37c0433458\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/system_modes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/system_modes/ to MongoDB with id 67427db9b98d7a37c0433459\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_transform_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_transform_util/ to MongoDB with id 67427db9b98d7a37c043345a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_system_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_system_util/ to MongoDB with id 67427dbab98d7a37c043345b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_serial_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_serial_util/ to MongoDB with id 67427dbab98d7a37c043345c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_route_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_route_util/ to MongoDB with id 67427dbbb98d7a37c043345d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_roscpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_roscpp/ to MongoDB with id 67427dbcb98d7a37c043345e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_opencv_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_opencv_util/ to MongoDB with id 67427dbcb98d7a37c043345f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_math_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_math_util/ to MongoDB with id 67427dbdb98d7a37c0433460\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_image_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_image_util/ to MongoDB with id 67427dbdb98d7a37c0433461\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_geometry_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_geometry_util/ to MongoDB with id 67427dbeb98d7a37c0433462\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_dbw_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_dbw_interface/ to MongoDB with id 67427dbeb98d7a37c0433463\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_console_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_console_util/ to MongoDB with id 67427dbfb98d7a37c0433464\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_console/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_console/ to MongoDB with id 67427dbfb98d7a37c0433465\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/swri_cli_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/swri_cli_tools/ to MongoDB with id 67427dc0b98d7a37c0433466\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/stomp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/stomp/ to MongoDB with id 67427dc0b98d7a37c0433467\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/stereo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/stereo_msgs/ to MongoDB with id 67427dc1b98d7a37c0433468\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/stereo_image_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/stereo_image_proc/ to MongoDB with id 67427dc1b98d7a37c0433469\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/steering_functions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/steering_functions/ to MongoDB with id 67427dc2b98d7a37c043346a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/steering_controllers_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/steering_controllers_library/ to MongoDB with id 67427dc2b98d7a37c043346b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/std_srvs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/std_srvs/ to MongoDB with id 67427dc3b98d7a37c043346c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/std_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/std_msgs/ to MongoDB with id 67427dc3b98d7a37c043346d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sros2/ to MongoDB with id 67427dc4b98d7a37c043346e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/srdfdom/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/srdfdom/ to MongoDB with id 67427dc4b98d7a37c043346f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sr_event_countdown/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sr_event_countdown/ to MongoDB with id 67427dc5b98d7a37c0433470\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sr_conditional/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sr_conditional/ to MongoDB with id 67427dc5b98d7a37c0433471\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sr_all_events_go/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sr_all_events_go/ to MongoDB with id 67427dc6b98d7a37c0433472\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sqlite3_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sqlite3_vendor/ to MongoDB with id 67427dc6b98d7a37c0433473\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/splsm_8_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/splsm_8_conversion/ to MongoDB with id 67427dc7b98d7a37c0433474\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/splsm_7_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/splsm_7_conversion/ to MongoDB with id 67427dc7b98d7a37c0433475\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/spinnaker_synchronized_camera_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/spinnaker_synchronized_camera_driver/ to MongoDB with id 67427dc8b98d7a37c0433476\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/spinnaker_camera_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/spinnaker_camera_driver/ to MongoDB with id 67427dc8b98d7a37c0433477\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/spatio_temporal_voxel_layer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/spatio_temporal_voxel_layer/ to MongoDB with id 67427dc9b98d7a37c0433478\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/spacenav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/spacenav/ to MongoDB with id 67427dc9b98d7a37c0433479\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sophus/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sophus/ to MongoDB with id 67427dc9b98d7a37c043347a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/social_nav_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/social_nav_util/ to MongoDB with id 67427dcab98d7a37c043347b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/social_nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/social_nav_msgs/ to MongoDB with id 67427dcab98d7a37c043347c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/social_nav_metrics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/social_nav_metrics/ to MongoDB with id 67427dcbb98d7a37c043347d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/soccer_vision_3d_rviz_markers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/soccer_vision_3d_rviz_markers/ to MongoDB with id 67427dcbb98d7a37c043347e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/snowbot_operating_system/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/snowbot_operating_system/ to MongoDB with id 67427dcbb98d7a37c043347f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/smclib/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/smclib/ to MongoDB with id 67427dccb98d7a37c0433480\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/smach_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/smach_ros/ to MongoDB with id 67427dccb98d7a37c0433481\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/smach_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/smach_msgs/ to MongoDB with id 67427dcdb98d7a37c0433482\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/smach/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/smach/ to MongoDB with id 67427dcdb98d7a37c0433483\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/smacc2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/smacc2/ to MongoDB with id 67427dceb98d7a37c0433484\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_three_some/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_three_some/ to MongoDB with id 67427dcfb98d7a37c0433485\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_test_moveit_ur5_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_test_moveit_ur5_sim/ to MongoDB with id 67427dd0b98d7a37c0433486\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_respira_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_respira_1/ to MongoDB with id 67427dd1b98d7a37c0433487\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_pubsub_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_pubsub_1/ to MongoDB with id 67427dd2b98d7a37c0433488\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_pack_ml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_pack_ml/ to MongoDB with id 67427dd3b98d7a37c0433489\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_multi_ur5_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_multi_ur5_sim/ to MongoDB with id 67427dd4b98d7a37c043348a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_multi_stage_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_multi_stage_1/ to MongoDB with id 67427dd6b98d7a37c043348b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_husky_barrel_search_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_husky_barrel_search_1/ to MongoDB with id 67427dd6b98d7a37c043348c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_dance_bot_warehouse_3/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_dance_bot_warehouse_3/ to MongoDB with id 67427dd8b98d7a37c043348d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_dance_bot_warehouse_2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_dance_bot_warehouse_2/ to MongoDB with id 67427dd9b98d7a37c043348e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_dance_bot_warehouse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_dance_bot_warehouse/ to MongoDB with id 67427ddab98d7a37c043348f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_dance_bot_strikes_back/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_dance_bot_strikes_back/ to MongoDB with id 67427ddbb98d7a37c0433490\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_dance_bot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_dance_bot/ to MongoDB with id 67427ddcb98d7a37c0433491\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_coretest_transition_speed_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_coretest_transition_speed_1/ to MongoDB with id 67427ddcb98d7a37c0433492\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_branching/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_branching/ to MongoDB with id 67427dddb98d7a37c0433493\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_aws_warehouse_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_aws_warehouse_navigation/ to MongoDB with id 67427ddeb98d7a37c0433494\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_autoware_avp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_autoware_avp/ to MongoDB with id 67427ddfb98d7a37c0433495\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_atomic_subscribers_performance_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_atomic_subscribers_performance_test/ to MongoDB with id 67427ddfb98d7a37c0433496\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_atomic_services/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_atomic_services/ to MongoDB with id 67427de0b98d7a37c0433497\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_atomic_performance_trace_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_atomic_performance_trace_1/ to MongoDB with id 67427de0b98d7a37c0433498\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_atomic_hierarchy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_atomic_hierarchy/ to MongoDB with id 67427de1b98d7a37c0433499\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_atomic_24hr/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_atomic_24hr/ to MongoDB with id 67427de1b98d7a37c043349a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_atomic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_atomic/ to MongoDB with id 67427de2b98d7a37c043349b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sm_advanced_recovery_1/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sm_advanced_recovery_1/ to MongoDB with id 67427de3b98d7a37c043349c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/slider_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/slider_publisher/ to MongoDB with id 67427de3b98d7a37c043349d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/slam_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/slam_toolbox/ to MongoDB with id 67427de4b98d7a37c043349e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/situational_graphs_datasets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/situational_graphs_datasets/ to MongoDB with id 67427de5b98d7a37c043349f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/simple_grasping/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/simple_grasping/ to MongoDB with id 67427de5b98d7a37c04334a0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/simple_actions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/simple_actions/ to MongoDB with id 67427de6b98d7a37c04334a1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sick_scan_xd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sick_scan_xd/ to MongoDB with id 67427de8b98d7a37c04334a2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sick_safevisionary_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sick_safevisionary_tests/ to MongoDB with id 67427de8b98d7a37c04334a3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sick_safetyscanners_base/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sick_safetyscanners_base/ to MongoDB with id 67427de9b98d7a37c04334a4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sick_safetyscanners2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sick_safetyscanners2/ to MongoDB with id 67427deab98d7a37c04334a5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/shared_queues_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/shared_queues_vendor/ to MongoDB with id 67427deab98d7a37c04334a6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/shape_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/shape_msgs/ to MongoDB with id 67427debb98d7a37c04334a7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/serial_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/serial_driver/ to MongoDB with id 67427debb98d7a37c04334a8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/septentrio_gnss_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/septentrio_gnss_driver/ to MongoDB with id 67427dedb98d7a37c04334a9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sensor_msgs_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sensor_msgs_py/ to MongoDB with id 67427dedb98d7a37c04334aa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sensor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sensor_msgs/ to MongoDB with id 67427deeb98d7a37c04334ab\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/self_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/self_test/ to MongoDB with id 67427defb98d7a37c04334ac\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sdformat_urdf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sdformat_urdf/ to MongoDB with id 67427defb98d7a37c04334ad\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sdc21x0/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sdc21x0/ to MongoDB with id 67427defb98d7a37c04334ae\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/sbg_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/sbg_driver/ to MongoDB with id 67427df0b98d7a37c04334af\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_visual_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_visual_tools/ to MongoDB with id 67427df1b98d7a37c04334b0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_visual_testing_framework/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_visual_testing_framework/ to MongoDB with id 67427df1b98d7a37c04334b1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_satellite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_satellite/ to MongoDB with id 67427df2b98d7a37c04334b2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_rendering_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_rendering_tests/ to MongoDB with id 67427df2b98d7a37c04334b3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_rendering/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_rendering/ to MongoDB with id 67427df3b98d7a37c04334b4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_ogre_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_ogre_vendor/ to MongoDB with id 67427df3b98d7a37c04334b5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_imu_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_imu_plugin/ to MongoDB with id 67427df4b98d7a37c04334b6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_default_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_default_plugins/ to MongoDB with id 67427df4b98d7a37c04334b7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_assimp_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_assimp_vendor/ to MongoDB with id 67427df5b98d7a37c04334b8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz_2d_overlay_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz_2d_overlay_plugins/ to MongoDB with id 67427df5b98d7a37c04334b9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rviz2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rviz2/ to MongoDB with id 67427df6b98d7a37c04334ba\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rttest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rttest/ to MongoDB with id 67427df7b98d7a37c04334bb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtcm_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtcm_msgs/ to MongoDB with id 67427df7b98d7a37c04334bc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_viz/ to MongoDB with id 67427df8b98d7a37c04334bd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_util/ to MongoDB with id 67427df8b98d7a37c04334be\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_sync/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_sync/ to MongoDB with id 67427df8b98d7a37c04334bf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_slam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_slam/ to MongoDB with id 67427df9b98d7a37c04334c0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_rviz_plugins/ to MongoDB with id 67427df9b98d7a37c04334c1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_ros/ to MongoDB with id 67427dfab98d7a37c04334c2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_python/ to MongoDB with id 67427dfab98d7a37c04334c3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_odom/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_odom/ to MongoDB with id 67427dfbb98d7a37c04334c4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_msgs/ to MongoDB with id 67427dfcb98d7a37c04334c5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_launch/ to MongoDB with id 67427dfcb98d7a37c04334c6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_examples/ to MongoDB with id 67427dfdb98d7a37c04334c7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_demos/ to MongoDB with id 67427dfdb98d7a37c04334c8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap_conversions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap_conversions/ to MongoDB with id 67427dfeb98d7a37c04334c9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rtabmap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rtabmap/ to MongoDB with id 67427dfeb98d7a37c04334ca\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rt_manipulators_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rt_manipulators_examples/ to MongoDB with id 67427dfeb98d7a37c04334cb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rt_manipulators_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rt_manipulators_cpp/ to MongoDB with id 67427dffb98d7a37c04334cc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rsl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rsl/ to MongoDB with id 67427e00b98d7a37c04334cd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rrt_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rrt_planner/ to MongoDB with id 67427e00b98d7a37c04334ce\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_joint_trajectory_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_joint_trajectory_controller/ to MongoDB with id 67427e00b98d7a37c04334cf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_image_view/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_image_view/ to MongoDB with id 67427e01b98d7a37c04334d0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_image_overlay_layer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_image_overlay_layer/ to MongoDB with id 67427e01b98d7a37c04334d1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_gui_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_gui_cpp/ to MongoDB with id 67427e02b98d7a37c04334d2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_graph/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_graph/ to MongoDB with id 67427e02b98d7a37c04334d3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_dotgraph/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_dotgraph/ to MongoDB with id 67427e03b98d7a37c04334d4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_controller_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_controller_manager/ to MongoDB with id 67427e03b98d7a37c04334d5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_bag_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_bag_plugins/ to MongoDB with id 67427e04b98d7a37c04334d6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rqt_bag/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rqt_bag/ to MongoDB with id 67427e05b98d7a37c04334d7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rpyutils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rpyutils/ to MongoDB with id 67427e05b98d7a37c04334d8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosx_introspection/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosx_introspection/ to MongoDB with id 67427e06b98d7a37c04334d9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_introspection_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_introspection_tests/ to MongoDB with id 67427e06b98d7a37c04334da\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_introspection_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_introspection_cpp/ to MongoDB with id 67427e07b98d7a37c04334db\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_introspection_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_introspection_c/ to MongoDB with id 67427e07b98d7a37c04334dc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_interface/ to MongoDB with id 67427e08b98d7a37c04334dd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_fastrtps_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_fastrtps_cpp/ to MongoDB with id 67427e08b98d7a37c04334de\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_fastrtps_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_fastrtps_c/ to MongoDB with id 67427e09b98d7a37c04334df\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_cpp/ to MongoDB with id 67427e09b98d7a37c04334e0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_typesupport_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_typesupport_c/ to MongoDB with id 67427e0ab98d7a37c04334e1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_runtime_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_runtime_py/ to MongoDB with id 67427e0ab98d7a37c04334e2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_runtime_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_runtime_cpp/ to MongoDB with id 67427e0bb98d7a37c04334e3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_runtime_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_runtime_c/ to MongoDB with id 67427e0cb98d7a37c04334e4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_pycommon/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_pycommon/ to MongoDB with id 67427e0db98d7a37c04334e5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_parser/ to MongoDB with id 67427e0db98d7a37c04334e6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_generator_type_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_generator_type_description/ to MongoDB with id 67427e0eb98d7a37c04334e7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_generator_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_generator_tests/ to MongoDB with id 67427e0eb98d7a37c04334e8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_generator_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_generator_cpp/ to MongoDB with id 67427e0eb98d7a37c04334e9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_generator_c/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_generator_c/ to MongoDB with id 67427e0fb98d7a37c04334ea\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_dynamic_typesupport_fastrtps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_dynamic_typesupport_fastrtps/ to MongoDB with id 67427e0fb98d7a37c04334eb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_dynamic_typesupport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_dynamic_typesupport/ to MongoDB with id 67427e10b98d7a37c04334ec\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_cmake/ to MongoDB with id 67427e11b98d7a37c04334ed\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_cli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_cli/ to MongoDB with id 67427e11b98d7a37c04334ee\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosidl_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosidl_adapter/ to MongoDB with id 67427e12b98d7a37c04334ef\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbridge_test_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbridge_test_msgs/ to MongoDB with id 67427e12b98d7a37c04334f0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbridge_suite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbridge_suite/ to MongoDB with id 67427e13b98d7a37c04334f1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbridge_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbridge_server/ to MongoDB with id 67427e13b98d7a37c04334f2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbridge_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbridge_msgs/ to MongoDB with id 67427e14b98d7a37c04334f3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbridge_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbridge_library/ to MongoDB with id 67427e14b98d7a37c04334f4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_transport/ to MongoDB with id 67427e15b98d7a37c04334f5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_tests/ to MongoDB with id 67427e15b98d7a37c04334f6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_test_msgdefs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_test_msgdefs/ to MongoDB with id 67427e16b98d7a37c04334f7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_test_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_test_common/ to MongoDB with id 67427e16b98d7a37c04334f8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_storage_sqlite3/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_storage_sqlite3/ to MongoDB with id 67427e17b98d7a37c04334f9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_storage_mcap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_storage_mcap/ to MongoDB with id 67427e18b98d7a37c04334fa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_storage_default_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_storage_default_plugins/ to MongoDB with id 67427e18b98d7a37c04334fb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_storage/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_storage/ to MongoDB with id 67427e19b98d7a37c04334fc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_py/ to MongoDB with id 67427e19b98d7a37c04334fd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_performance_benchmarking_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_performance_benchmarking_msgs/ to MongoDB with id 67427e1ab98d7a37c04334fe\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_performance_benchmarking/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_performance_benchmarking/ to MongoDB with id 67427e1ab98d7a37c04334ff\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_interfaces/ to MongoDB with id 67427e1ab98d7a37c0433500\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_examples_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_examples_py/ to MongoDB with id 67427e1bb98d7a37c0433501\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_examples_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_examples_cpp/ to MongoDB with id 67427e1bb98d7a37c0433502\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_cpp/ to MongoDB with id 67427e1cb98d7a37c0433503\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_compression_zstd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_compression_zstd/ to MongoDB with id 67427e1cb98d7a37c0433504\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2_compression/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2_compression/ to MongoDB with id 67427e1db98d7a37c0433505\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosbag2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosbag2/ to MongoDB with id 67427e1db98d7a37c0433506\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosapi_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosapi_msgs/ to MongoDB with id 67427e1eb98d7a37c0433507\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rosapi/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rosapi/ to MongoDB with id 67427e1eb98d7a37c0433508\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_image_to_qimage/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_image_to_qimage/ to MongoDB with id 67427e1fb98d7a37c0433509\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_ign_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_ign_interfaces/ to MongoDB with id 67427e1fb98d7a37c043350a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_ign_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_ign_image/ to MongoDB with id 67427e20b98d7a37c043350b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_ign_gazebo_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_ign_gazebo_demos/ to MongoDB with id 67427e20b98d7a37c043350c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_ign_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_ign_gazebo/ to MongoDB with id 67427e21b98d7a37c043350d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_ign_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_ign_bridge/ to MongoDB with id 67427e21b98d7a37c043350e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_ign/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_ign/ to MongoDB with id 67427e21b98d7a37c043350f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_gz_sim_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_gz_sim_demos/ to MongoDB with id 67427e22b98d7a37c0433510\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_gz_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_gz_sim/ to MongoDB with id 67427e23b98d7a37c0433511\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_gz_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_gz_interfaces/ to MongoDB with id 67427e23b98d7a37c0433512\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_gz_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_gz_image/ to MongoDB with id 67427e23b98d7a37c0433513\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_gz_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_gz_bridge/ to MongoDB with id 67427e24b98d7a37c0433514\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros_gz/ to MongoDB with id 67427e25b98d7a37c0433515\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2trace_analysis/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2trace_analysis/ to MongoDB with id 67427e25b98d7a37c0433516\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2trace/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2trace/ to MongoDB with id 67427e26b98d7a37c0433517\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2topic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2topic/ to MongoDB with id 67427e26b98d7a37c0433518\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2test/ to MongoDB with id 67427e27b98d7a37c0433519\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2service/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2service/ to MongoDB with id 67427e27b98d7a37c043351a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2run/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2run/ to MongoDB with id 67427e28b98d7a37c043351b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2pkg/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2pkg/ to MongoDB with id 67427e29b98d7a37c043351c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2param/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2param/ to MongoDB with id 67427e2ab98d7a37c043351d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2nodl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2nodl/ to MongoDB with id 67427e2ab98d7a37c043351e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2node/ to MongoDB with id 67427e2bb98d7a37c043351f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2multicast/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2multicast/ to MongoDB with id 67427e2bb98d7a37c0433520\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2lifecycle_test_fixtures/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2lifecycle_test_fixtures/ to MongoDB with id 67427e2bb98d7a37c0433521\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2lifecycle/ to MongoDB with id 67427e2cb98d7a37c0433522\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2launch_security/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2launch_security/ to MongoDB with id 67427e2cb98d7a37c0433523\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2launch/ to MongoDB with id 67427e2db98d7a37c0433524\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2interface/ to MongoDB with id 67427e2db98d7a37c0433525\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2doctor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2doctor/ to MongoDB with id 67427e2eb98d7a37c0433526\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2controlcli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2controlcli/ to MongoDB with id 67427e2eb98d7a37c0433527\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2component/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2component/ to MongoDB with id 67427e2fb98d7a37c0433528\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2cli_test_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2cli_test_interfaces/ to MongoDB with id 67427e30b98d7a37c0433529\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2cli/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2cli/ to MongoDB with id 67427e30b98d7a37c043352a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2bag/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2bag/ to MongoDB with id 67427e30b98d7a37c043352b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2action/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2action/ to MongoDB with id 67427e31b98d7a37c043352c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2acceleration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2acceleration/ to MongoDB with id 67427e31b98d7a37c043352d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_socketcan_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_socketcan_msgs/ to MongoDB with id 67427e32b98d7a37c043352e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_socketcan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_socketcan/ to MongoDB with id 67427e33b98d7a37c043352f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_ouster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_ouster/ to MongoDB with id 67427e33b98d7a37c0433530\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_controllers_test_nodes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_controllers_test_nodes/ to MongoDB with id 67427e34b98d7a37c0433531\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_controllers/ to MongoDB with id 67427e34b98d7a37c0433532\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_control_test_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_control_test_assets/ to MongoDB with id 67427e35b98d7a37c0433533\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros2_control/ to MongoDB with id 67427e35b98d7a37c0433534\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ros1_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ros1_bridge/ to MongoDB with id 67427e36b98d7a37c0433535\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robotiq_hardware_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robotiq_hardware_tests/ to MongoDB with id 67427e37b98d7a37c0433536\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robotiq_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robotiq_driver/ to MongoDB with id 67427e37b98d7a37c0433537\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robotiq_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robotiq_description/ to MongoDB with id 67427e37b98d7a37c0433538\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robotiq_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robotiq_controllers/ to MongoDB with id 67427e38b98d7a37c0433539\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robot_state_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robot_state_publisher/ to MongoDB with id 67427e38b98d7a37c043353a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robot_calibration_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robot_calibration_msgs/ to MongoDB with id 67427e39b98d7a37c043353b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/robot_calibration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/robot_calibration/ to MongoDB with id 67427e39b98d7a37c043353c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_implementation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_implementation/ to MongoDB with id 67427e3ab98d7a37c043353d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_gurumdds_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_gurumdds_cpp/ to MongoDB with id 67427e3bb98d7a37c043353e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_fastrtps_shared_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_fastrtps_shared_cpp/ to MongoDB with id 67427e3bb98d7a37c043353f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_fastrtps_dynamic_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_fastrtps_dynamic_cpp/ to MongoDB with id 67427e3cb98d7a37c0433540\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_fastrtps_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_fastrtps_cpp/ to MongoDB with id 67427e3cb98d7a37c0433541\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_dds_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_dds_common/ to MongoDB with id 67427e3db98d7a37c0433542\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw_connextdds_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw_connextdds_common/ to MongoDB with id 67427e3eb98d7a37c0433543\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmw/ to MongoDB with id 67427e3fb98d7a37c0433544\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_workcell_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_workcell_msgs/ to MongoDB with id 67427e3fb98d7a37c0433545\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_websocket/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_websocket/ to MongoDB with id 67427e40b98d7a37c0433546\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_visualization_building_systems/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_visualization_building_systems/ to MongoDB with id 67427e40b98d7a37c0433547\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_utils/ to MongoDB with id 67427e41b98d7a37c0433548\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_traffic_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_traffic_ros2/ to MongoDB with id 67427e42b98d7a37c0433549\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_traffic_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_traffic_msgs/ to MongoDB with id 67427e43b98d7a37c043354a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_traffic_editor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_traffic_editor/ to MongoDB with id 67427e44b98d7a37c043354b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_traffic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_traffic/ to MongoDB with id 67427e45b98d7a37c043354c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_task_sequence/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_task_sequence/ to MongoDB with id 67427e45b98d7a37c043354d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_task_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_task_ros2/ to MongoDB with id 67427e46b98d7a37c043354e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_task_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_task_msgs/ to MongoDB with id 67427e46b98d7a37c043354f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_task/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_task/ to MongoDB with id 67427e47b98d7a37c0433550\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_site_map_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_site_map_msgs/ to MongoDB with id 67427e48b98d7a37c0433551\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_scheduler_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_scheduler_msgs/ to MongoDB with id 67427e48b98d7a37c0433552\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_robot_sim_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_robot_sim_common/ to MongoDB with id 67427e49b98d7a37c0433553\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_obstacle_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_obstacle_msgs/ to MongoDB with id 67427e49b98d7a37c0433554\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_lift_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_lift_msgs/ to MongoDB with id 67427e4ab98d7a37c0433555\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_ingestor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_ingestor_msgs/ to MongoDB with id 67427e4ab98d7a37c0433556\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_fleet_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_fleet_msgs/ to MongoDB with id 67427e4ab98d7a37c0433557\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_fleet_adapter_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_fleet_adapter_python/ to MongoDB with id 67427e4bb98d7a37c0433558\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_fleet_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_fleet_adapter/ to MongoDB with id 67427e4cb98d7a37c0433559\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_door_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_door_msgs/ to MongoDB with id 67427e4cb98d7a37c043355a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_dispenser_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_dispenser_msgs/ to MongoDB with id 67427e4db98d7a37c043355b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_dev/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_dev/ to MongoDB with id 67427e4db98d7a37c043355c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_tasks/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_tasks/ to MongoDB with id 67427e4eb98d7a37c043355d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_panel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_panel/ to MongoDB with id 67427e4eb98d7a37c043355e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_maps/ to MongoDB with id 67427e4fb98d7a37c043355f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_gz_classic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_gz_classic/ to MongoDB with id 67427e4fb98d7a37c0433560\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_gz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_gz/ to MongoDB with id 67427e4fb98d7a37c0433561\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_fleet_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_fleet_adapter/ to MongoDB with id 67427e50b98d7a37c0433562\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_dashboard_resources/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_dashboard_resources/ to MongoDB with id 67427e50b98d7a37c0433563\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_bridges/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_bridges/ to MongoDB with id 67427e51b98d7a37c0433564\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos_assets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos_assets/ to MongoDB with id 67427e51b98d7a37c0433565\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_demos/ to MongoDB with id 67427e52b98d7a37c0433566\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_charging_schedule/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_charging_schedule/ to MongoDB with id 67427e52b98d7a37c0433567\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_charger_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_charger_msgs/ to MongoDB with id 67427e53b98d7a37c0433568\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_building_sim_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_building_sim_common/ to MongoDB with id 67427e54b98d7a37c0433569\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_battery/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_battery/ to MongoDB with id 67427e54b98d7a37c043356a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rmf_api_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rmf_api_msgs/ to MongoDB with id 67427e55b98d7a37c043356b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/resource_retriever/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/resource_retriever/ to MongoDB with id 67427e55b98d7a37c043356c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/realtime_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/realtime_tools/ to MongoDB with id 67427e56b98d7a37c043356d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/realsense2_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/realsense2_description/ to MongoDB with id 67427e56b98d7a37c043356e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/realsense2_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/realsense2_camera_msgs/ to MongoDB with id 67427e57b98d7a37c043356f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/realsense2_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/realsense2_camera/ to MongoDB with id 67427e57b98d7a37c0433570\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcutils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcutils/ to MongoDB with id 67427e58b98d7a37c0433571\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcss3d_nao/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcss3d_nao/ to MongoDB with id 67427e58b98d7a37c0433572\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcss3d_agent_msgs_to_soccer_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcss3d_agent_msgs_to_soccer_interfaces/ to MongoDB with id 67427e59b98d7a37c0433573\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcss3d_agent_basic/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcss3d_agent_basic/ to MongoDB with id 67427e59b98d7a37c0433574\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcss3d_agent/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcss3d_agent/ to MongoDB with id 67427e5ab98d7a37c0433575\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcpputils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcpputils/ to MongoDB with id 67427e5ab98d7a37c0433576\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclpy_message_converter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclpy_message_converter/ to MongoDB with id 67427e5bb98d7a37c0433577\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclpy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclpy/ to MongoDB with id 67427e5bb98d7a37c0433578\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclcpp_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclcpp_lifecycle/ to MongoDB with id 67427e5cb98d7a37c0433579\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclcpp_components/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclcpp_components/ to MongoDB with id 67427e5cb98d7a37c043357a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclcpp_cascade_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclcpp_cascade_lifecycle/ to MongoDB with id 67427e5db98d7a37c043357b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclcpp_action/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclcpp_action/ to MongoDB with id 67427e5db98d7a37c043357c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclcpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclcpp/ to MongoDB with id 67427e5eb98d7a37c043357d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclc_parameter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclc_parameter/ to MongoDB with id 67427e5eb98d7a37c043357e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclc_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclc_lifecycle/ to MongoDB with id 67427e5fb98d7a37c043357f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rclc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rclc/ to MongoDB with id 67427e5fb98d7a37c0433580\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_yaml_param_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_yaml_param_parser/ to MongoDB with id 67427e60b98d7a37c0433581\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_logging_spdlog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_logging_spdlog/ to MongoDB with id 67427e60b98d7a37c0433582\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_logging_rcutils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_logging_rcutils/ to MongoDB with id 67427e61b98d7a37c0433583\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_logging_noop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_logging_noop/ to MongoDB with id 67427e61b98d7a37c0433584\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_logging_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_logging_interface/ to MongoDB with id 67427e62b98d7a37c0433585\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_lifecycle/ to MongoDB with id 67427e62b98d7a37c0433586\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl_action/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl_action/ to MongoDB with id 67427e63b98d7a37c0433587\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcl/ to MongoDB with id 67427e63b98d7a37c0433588\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcgcrd_spl_4_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcgcrd_spl_4_conversion/ to MongoDB with id 67427e64b98d7a37c0433589\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcgcd_spl_14_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcgcd_spl_14_conversion/ to MongoDB with id 67427e64b98d7a37c043358a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rcdiscover/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rcdiscover/ to MongoDB with id 67427e65b98d7a37c043358b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rc_reason_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rc_reason_msgs/ to MongoDB with id 67427e65b98d7a37c043358c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rc_reason_clients/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rc_reason_clients/ to MongoDB with id 67427e66b98d7a37c043358d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rc_genicam_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rc_genicam_driver/ to MongoDB with id 67427e66b98d7a37c043358e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/rc_genicam_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/rc_genicam_api/ to MongoDB with id 67427e67b98d7a37c043358f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/range_sensor_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/range_sensor_broadcaster/ to MongoDB with id 67427e68b98d7a37c0433590\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/random_numbers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/random_numbers/ to MongoDB with id 67427e68b98d7a37c0433591\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/r2r_spl_8/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/r2r_spl_8/ to MongoDB with id 67427e69b98d7a37c0433592\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/r2r_spl_7/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/r2r_spl_7/ to MongoDB with id 67427e69b98d7a37c0433593\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/r2r_spl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/r2r_spl/ to MongoDB with id 67427e69b98d7a37c0433594\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/quaternion_operation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/quaternion_operation/ to MongoDB with id 67427e6ab98d7a37c0433595\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/quality_of_service_demo_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/quality_of_service_demo_py/ to MongoDB with id 67427e6ab98d7a37c0433596\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/quality_of_service_demo_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/quality_of_service_demo_cpp/ to MongoDB with id 67427e6bb98d7a37c0433597\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/qt_gui_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/qt_gui_cpp/ to MongoDB with id 67427e6bb98d7a37c0433598\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/python_mrpt/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/python_mrpt/ to MongoDB with id 67427e6cb98d7a37c0433599\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/py_trees_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/py_trees_ros/ to MongoDB with id 67427e6db98d7a37c043359a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/py_trees_js/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/py_trees_js/ to MongoDB with id 67427e6db98d7a37c043359b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/py_trees/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/py_trees/ to MongoDB with id 67427e6eb98d7a37c043359c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pure_spinning_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pure_spinning_local_planner/ to MongoDB with id 67427e6eb98d7a37c043359d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/proxsuite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/proxsuite/ to MongoDB with id 67427e6fb98d7a37c043359e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/position_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/position_controllers/ to MongoDB with id 67427e70b98d7a37c043359f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pose_cov_ops/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pose_cov_ops/ to MongoDB with id 67427e70b98d7a37c04335a0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pose_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pose_broadcaster/ to MongoDB with id 67427e71b98d7a37c04335a1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/polygon_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/polygon_utils/ to MongoDB with id 67427e72b98d7a37c04335a2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/polygon_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/polygon_rviz_plugins/ to MongoDB with id 67427e72b98d7a37c04335a3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/polygon_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/polygon_msgs/ to MongoDB with id 67427e72b98d7a37c04335a4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/polygon_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/polygon_demos/ to MongoDB with id 67427e73b98d7a37c04335a5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pointcloud_to_laserscan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pointcloud_to_laserscan/ to MongoDB with id 67427e73b98d7a37c04335a6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/point_cloud_transport_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/point_cloud_transport_py/ to MongoDB with id 67427e74b98d7a37c04335a7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/point_cloud_transport_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/point_cloud_transport_plugins/ to MongoDB with id 67427e74b98d7a37c04335a8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/point_cloud_transport/ to MongoDB with id 67427e75b98d7a37c04335a9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/point_cloud_msg_wrapper/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/point_cloud_msg_wrapper/ to MongoDB with id 67427e75b98d7a37c04335aa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/point_cloud_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/point_cloud_interfaces/ to MongoDB with id 67427e76b98d7a37c04335ab\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pluginlib/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pluginlib/ to MongoDB with id 67427e76b98d7a37c04335ac\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plotjuggler_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plotjuggler_ros/ to MongoDB with id 67427e77b98d7a37c04335ad\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plotjuggler/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plotjuggler/ to MongoDB with id 67427e77b98d7a37c04335ae\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_tools/ to MongoDB with id 67427e78b98d7a37c04335af\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_tests/ to MongoDB with id 67427e78b98d7a37c04335b0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_terminal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_terminal/ to MongoDB with id 67427e79b98d7a37c04335b1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_problem_expert/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_problem_expert/ to MongoDB with id 67427e79b98d7a37c04335b2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_popf_plan_solver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_popf_plan_solver/ to MongoDB with id 67427e7ab98d7a37c04335b3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_planner/ to MongoDB with id 67427e7ab98d7a37c04335b4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_pddl_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_pddl_parser/ to MongoDB with id 67427e7bb98d7a37c04335b5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_lifecycle_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_lifecycle_manager/ to MongoDB with id 67427e7cb98d7a37c04335b6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_executor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_executor/ to MongoDB with id 67427e7cb98d7a37c04335b7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_domain_expert/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_domain_expert/ to MongoDB with id 67427e7db98d7a37c04335b8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/plansys2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/plansys2_core/ to MongoDB with id 67427e7eb98d7a37c04335b9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pilz_industrial_motion_planner_testutils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pilz_industrial_motion_planner_testutils/ to MongoDB with id 67427e7eb98d7a37c04335ba\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pilz_industrial_motion_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pilz_industrial_motion_planner/ to MongoDB with id 67427e7fb98d7a37c04335bb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pid_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pid_controller/ to MongoDB with id 67427e7fb98d7a37c04335bc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/picknik_twist_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/picknik_twist_controller/ to MongoDB with id 67427e80b98d7a37c04335bd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/picknik_reset_fault_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/picknik_reset_fault_controller/ to MongoDB with id 67427e80b98d7a37c04335be\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pick_ik/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pick_ik/ to MongoDB with id 67427e81b98d7a37c04335bf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_temperature/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_temperature/ to MongoDB with id 67427e81b98d7a37c04335c0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_spatial/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_spatial/ to MongoDB with id 67427e82b98d7a37c04335c1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_motors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_motors/ to MongoDB with id 67427e82b98d7a37c04335c2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_magnetometer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_magnetometer/ to MongoDB with id 67427e82b98d7a37c04335c3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_high_speed_encoder/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_high_speed_encoder/ to MongoDB with id 67427e83b98d7a37c04335c4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_gyroscope/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_gyroscope/ to MongoDB with id 67427e84b98d7a37c04335c5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_digital_outputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_digital_outputs/ to MongoDB with id 67427e84b98d7a37c04335c6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_digital_inputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_digital_inputs/ to MongoDB with id 67427e85b98d7a37c04335c7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_api/ to MongoDB with id 67427e86b98d7a37c04335c8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_analog_outputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_analog_outputs/ to MongoDB with id 67427e86b98d7a37c04335c9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_analog_inputs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_analog_inputs/ to MongoDB with id 67427e86b98d7a37c04335ca\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/phidgets_accelerometer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/phidgets_accelerometer/ to MongoDB with id 67427e87b98d7a37c04335cb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/performance_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/performance_test/ to MongoDB with id 67427e88b98d7a37c04335cc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/performance_report/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/performance_report/ to MongoDB with id 67427e88b98d7a37c04335cd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/perception_pcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/perception_pcl/ to MongoDB with id 67427e89b98d7a37c04335ce\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pendulum_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pendulum_msgs/ to MongoDB with id 67427e89b98d7a37c04335cf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pendulum_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pendulum_control/ to MongoDB with id 67427e8ab98d7a37c04335d0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pcl_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pcl_ros/ to MongoDB with id 67427e8ab98d7a37c04335d1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/pcl_conversions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/pcl_conversions/ to MongoDB with id 67427e8bb98d7a37c04335d2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/parameter_traits/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/parameter_traits/ to MongoDB with id 67427e8bb98d7a37c04335d3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/osrf_testing_tools_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/osrf_testing_tools_cpp/ to MongoDB with id 67427e8cb98d7a37c04335d4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/osrf_pycommon/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/osrf_pycommon/ to MongoDB with id 67427e8db98d7a37c04335d5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/osqp_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/osqp_vendor/ to MongoDB with id 67427e8db98d7a37c04335d6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/openvdb_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/openvdb_vendor/ to MongoDB with id 67427e8eb98d7a37c04335d7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/opensw_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/opensw_ros/ to MongoDB with id 67427e8eb98d7a37c04335d8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/opensw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/opensw/ to MongoDB with id 67427e8fb98d7a37c04335d9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/openni2_camera/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/openni2_camera/ to MongoDB with id 67427e8fb98d7a37c04335da\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/openeb_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/openeb_vendor/ to MongoDB with id 67427e90b98d7a37c04335db\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/opencv_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/opencv_tests/ to MongoDB with id 67427e91b98d7a37c04335dc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ompl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ompl/ to MongoDB with id 67427e91b98d7a37c04335dd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/odom_to_tf_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/odom_to_tf_ros2/ to MongoDB with id 67427e92b98d7a37c04335de\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octovis/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octovis/ to MongoDB with id 67427e92b98d7a37c04335df\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octomap_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octomap_server/ to MongoDB with id 67427e93b98d7a37c04335e0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octomap_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octomap_rviz_plugins/ to MongoDB with id 67427e94b98d7a37c04335e1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octomap_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octomap_ros/ to MongoDB with id 67427e94b98d7a37c04335e2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octomap_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octomap_msgs/ to MongoDB with id 67427e95b98d7a37c04335e3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octomap_mapping/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octomap_mapping/ to MongoDB with id 67427e95b98d7a37c04335e4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/octomap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/octomap/ to MongoDB with id 67427e96b98d7a37c04335e5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ntrip_client_node/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ntrip_client_node/ to MongoDB with id 67427e97b98d7a37c04335e6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ntpd_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ntpd_driver/ to MongoDB with id 67427e97b98d7a37c04335e7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/novatel_gps_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/novatel_gps_msgs/ to MongoDB with id 67427e98b98d7a37c04335e8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/novatel_gps_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/novatel_gps_driver/ to MongoDB with id 67427e98b98d7a37c04335e9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nodl_to_policy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nodl_to_policy/ to MongoDB with id 67427e99b98d7a37c04335ea\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nmea_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nmea_msgs/ to MongoDB with id 67427e99b98d7a37c04335eb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nmea_hardware_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nmea_hardware_interface/ to MongoDB with id 67427e9ab98d7a37c04335ec\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/neo_simulation2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/neo_simulation2/ to MongoDB with id 67427e9ab98d7a37c04335ed\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/neo_nav2_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/neo_nav2_bringup/ to MongoDB with id 67427e9bb98d7a37c04335ee\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ndt_omp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ndt_omp/ to MongoDB with id 67427e9bb98d7a37c04335ef\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/navigation2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/navigation2/ to MongoDB with id 67427e9cb98d7a37c04335f0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav_msgs/ to MongoDB with id 67427e9cb98d7a37c04335f1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav_2d_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav_2d_utils/ to MongoDB with id 67427e9db98d7a37c04335f2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav_2d_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav_2d_msgs/ to MongoDB with id 67427e9db98d7a37c04335f3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2z_planners_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2z_planners_common/ to MongoDB with id 67427e9db98d7a37c04335f4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_waypoint_follower/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_waypoint_follower/ to MongoDB with id 67427e9eb98d7a37c04335f5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_voxel_grid/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_voxel_grid/ to MongoDB with id 67427e9fb98d7a37c04335f6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_velocity_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_velocity_smoother/ to MongoDB with id 67427e9fb98d7a37c04335f7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_util/ to MongoDB with id 67427ea0b98d7a37c04335f8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_theta_star_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_theta_star_planner/ to MongoDB with id 67427ea0b98d7a37c04335f9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_system_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_system_tests/ to MongoDB with id 67427ea0b98d7a37c04335fa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_smoother/ to MongoDB with id 67427ea1b98d7a37c04335fb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_smac_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_smac_planner/ to MongoDB with id 67427ea1b98d7a37c04335fc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_simple_commander/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_simple_commander/ to MongoDB with id 67427ea2b98d7a37c04335fd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_rviz_plugins/ to MongoDB with id 67427ea3b98d7a37c04335fe\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_rotation_shim_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_rotation_shim_controller/ to MongoDB with id 67427ea3b98d7a37c04335ff\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_regulated_pure_pursuit_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_regulated_pure_pursuit_controller/ to MongoDB with id 67427ea4b98d7a37c0433600\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_planner/ to MongoDB with id 67427ea4b98d7a37c0433601\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_navfn_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_navfn_planner/ to MongoDB with id 67427ea5b98d7a37c0433602\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_msgs/ to MongoDB with id 67427ea5b98d7a37c0433603\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_mppi_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_mppi_controller/ to MongoDB with id 67427ea6b98d7a37c0433604\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_map_server/ to MongoDB with id 67427ea6b98d7a37c0433605\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_lifecycle_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_lifecycle_manager/ to MongoDB with id 67427ea7b98d7a37c0433606\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_dwb_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_dwb_controller/ to MongoDB with id 67427ea7b98d7a37c0433607\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_core/ to MongoDB with id 67427ea8b98d7a37c0433608\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_controller/ to MongoDB with id 67427ea8b98d7a37c0433609\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_constrained_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_constrained_smoother/ to MongoDB with id 67427ea9b98d7a37c043360a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_common/ to MongoDB with id 67427ea9b98d7a37c043360b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_collision_monitor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_collision_monitor/ to MongoDB with id 67427eaab98d7a37c043360c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_bt_navigator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_bt_navigator/ to MongoDB with id 67427eaab98d7a37c043360d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_bringup/ to MongoDB with id 67427eabb98d7a37c043360e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_behaviors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_behaviors/ to MongoDB with id 67427eabb98d7a37c043360f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_behavior_tree/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_behavior_tree/ to MongoDB with id 67427eacb98d7a37c0433610\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nav2_amcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nav2_amcl/ to MongoDB with id 67427eacb98d7a37c0433611\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nao_lola_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nao_lola_conversion/ to MongoDB with id 67427eadb98d7a37c0433612\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nao_lola_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nao_lola_client/ to MongoDB with id 67427eadb98d7a37c0433613\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nao_lola/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nao_lola/ to MongoDB with id 67427eaeb98d7a37c0433614\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/nao_button_sim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/nao_button_sim/ to MongoDB with id 67427eaeb98d7a37c0433615\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mvsim/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mvsim/ to MongoDB with id 67427eafb98d7a37c0433616\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/multires_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/multires_image/ to MongoDB with id 67427eafb98d7a37c0433617\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrt_cmake_modules/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrt_cmake_modules/ to MongoDB with id 67427eb0b98d7a37c0433618\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_tutorials/ to MongoDB with id 67427eb0b98d7a37c0433619\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_tps_astar_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_tps_astar_planner/ to MongoDB with id 67427eb1b98d7a37c043361a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_tclap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_tclap/ to MongoDB with id 67427eb1b98d7a37c043361b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_slam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_slam/ to MongoDB with id 67427eb2b98d7a37c043361c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensors/ to MongoDB with id 67427eb2b98d7a37c043361d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensorlib/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensorlib/ to MongoDB with id 67427eb3b98d7a37c043361e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensor_imu_taobotics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensor_imu_taobotics/ to MongoDB with id 67427eb3b98d7a37c043361f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensor_gnss_novatel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensor_gnss_novatel/ to MongoDB with id 67427eb3b98d7a37c0433620\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensor_gnss_nmea/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensor_gnss_nmea/ to MongoDB with id 67427eb4b98d7a37c0433621\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensor_gnns_novatel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensor_gnns_novatel/ to MongoDB with id 67427eb4b98d7a37c0433622\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensor_gnns_nmea/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensor_gnns_nmea/ to MongoDB with id 67427eb5b98d7a37c0433623\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_sensor_bumblebee_stereo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_sensor_bumblebee_stereo/ to MongoDB with id 67427eb5b98d7a37c0433624\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_ros2bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_ros2bridge/ to MongoDB with id 67427eb6b98d7a37c0433625\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_reactivenav2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_reactivenav2d/ to MongoDB with id 67427eb6b98d7a37c0433626\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_rawlog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_rawlog/ to MongoDB with id 67427eb6b98d7a37c0433627\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_poses/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_poses/ to MongoDB with id 67427eb7b98d7a37c0433628\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_pointcloud_pipeline/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_pointcloud_pipeline/ to MongoDB with id 67427eb9b98d7a37c0433629\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_pf_localization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_pf_localization/ to MongoDB with id 67427eb9b98d7a37c043362a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_opengl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_opengl/ to MongoDB with id 67427ebab98d7a37c043362b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_obs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_obs/ to MongoDB with id 67427ebab98d7a37c043362c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_navigation/ to MongoDB with id 67427ebbb98d7a37c043362d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_nav_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_nav_interfaces/ to MongoDB with id 67427ebbb98d7a37c043362e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_nav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_nav/ to MongoDB with id 67427ebcb98d7a37c043362f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_msgs_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_msgs_bridge/ to MongoDB with id 67427ebcb98d7a37c0433630\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_msgs/ to MongoDB with id 67427ebdb98d7a37c0433631\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_math/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_math/ to MongoDB with id 67427ebdb98d7a37c0433632\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_maps/ to MongoDB with id 67427ebdb98d7a37c0433633\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_map_server/ to MongoDB with id 67427ebeb98d7a37c0433634\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_map/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_map/ to MongoDB with id 67427ebfb98d7a37c0433635\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_localization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_localization/ to MongoDB with id 67427ebfb98d7a37c0433636\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_local_obstacles/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_local_obstacles/ to MongoDB with id 67427ec0b98d7a37c0433637\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libtclap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libtclap/ to MongoDB with id 67427ec0b98d7a37c0433638\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libslam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libslam/ to MongoDB with id 67427ec0b98d7a37c0433639\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libros_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libros_bridge/ to MongoDB with id 67427ec1b98d7a37c043363a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libros2bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libros2bridge/ to MongoDB with id 67427ec2b98d7a37c043363b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libposes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libposes/ to MongoDB with id 67427ec2b98d7a37c043363c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libopengl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libopengl/ to MongoDB with id 67427ec2b98d7a37c043363d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libobs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libobs/ to MongoDB with id 67427ec3b98d7a37c043363e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libnav/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libnav/ to MongoDB with id 67427ec4b98d7a37c043363f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libmath/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libmath/ to MongoDB with id 67427ec4b98d7a37c0433640\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libmaps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libmaps/ to MongoDB with id 67427ec5b98d7a37c0433641\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libhwdrivers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libhwdrivers/ to MongoDB with id 67427ec5b98d7a37c0433642\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libgui/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libgui/ to MongoDB with id 67427ec5b98d7a37c0433643\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libbase/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libbase/ to MongoDB with id 67427ec6b98d7a37c0433644\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_libapps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_libapps/ to MongoDB with id 67427ec6b98d7a37c0433645\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_hwdrivers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_hwdrivers/ to MongoDB with id 67427ec7b98d7a37c0433646\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_gui/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_gui/ to MongoDB with id 67427ec7b98d7a37c0433647\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_generic_sensor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_generic_sensor/ to MongoDB with id 67427ec8b98d7a37c0433648\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_base/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_base/ to MongoDB with id 67427ec8b98d7a37c0433649\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mrpt_apps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mrpt_apps/ to MongoDB with id 67427ec9b98d7a37c043364a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mqtt_client_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mqtt_client_interfaces/ to MongoDB with id 67427ec9b98d7a37c043364b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mqtt_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mqtt_client/ to MongoDB with id 67427ecab98d7a37c043364c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mp2p_icp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mp2p_icp/ to MongoDB with id 67427ecab98d7a37c043364d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_visual_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_visual_tools/ to MongoDB with id 67427ecbb98d7a37c043364e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_simple_controller_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_simple_controller_manager/ to MongoDB with id 67427ecbb98d7a37c043364f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_setup_srdf_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_setup_srdf_plugins/ to MongoDB with id 67427eccb98d7a37c0433650\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_setup_framework/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_setup_framework/ to MongoDB with id 67427eccb98d7a37c0433651\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_setup_core_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_setup_core_plugins/ to MongoDB with id 67427ecdb98d7a37c0433652\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_setup_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_setup_controllers/ to MongoDB with id 67427ecdb98d7a37c0433653\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_setup_assistant/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_setup_assistant/ to MongoDB with id 67427eceb98d7a37c0433654\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_setup_app_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_setup_app_plugins/ to MongoDB with id 67427eceb98d7a37c0433655\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_servo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_servo/ to MongoDB with id 67427ecfb98d7a37c0433656\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_runtime/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_runtime/ to MongoDB with id 67427ecfb98d7a37c0433657\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_warehouse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_warehouse/ to MongoDB with id 67427ed0b98d7a37c0433658\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_visualization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_visualization/ to MongoDB with id 67427ed0b98d7a37c0433659\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_trajectory_cache/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_trajectory_cache/ to MongoDB with id 67427ed1b98d7a37c043365a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_tests/ to MongoDB with id 67427ed1b98d7a37c043365b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_robot_interaction/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_robot_interaction/ to MongoDB with id 67427ed2b98d7a37c043365c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_planning_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_planning_interface/ to MongoDB with id 67427ed2b98d7a37c043365d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_planning/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_planning/ to MongoDB with id 67427ed3b98d7a37c043365e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_perception/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_perception/ to MongoDB with id 67427ed3b98d7a37c043365f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_occupancy_map_monitor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_occupancy_map_monitor/ to MongoDB with id 67427ed4b98d7a37c0433660\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_move_group/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_move_group/ to MongoDB with id 67427ed5b98d7a37c0433661\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_control_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_control_interface/ to MongoDB with id 67427ed5b98d7a37c0433662\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros_benchmarks/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros_benchmarks/ to MongoDB with id 67427ed6b98d7a37c0433663\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_ros/ to MongoDB with id 67427ed6b98d7a37c0433664\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_prbt_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_prbt_support/ to MongoDB with id 67427ed6b98d7a37c0433665\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_prbt_pg70_support/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_prbt_pg70_support/ to MongoDB with id 67427ed7b98d7a37c0433666\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_prbt_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_prbt_moveit_config/ to MongoDB with id 67427ed7b98d7a37c0433667\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_prbt_ikfast_manipulator_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_prbt_ikfast_manipulator_plugin/ to MongoDB with id 67427ed8b98d7a37c0433668\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_pr2_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_pr2_description/ to MongoDB with id 67427ed8b98d7a37c0433669\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_panda_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_panda_moveit_config/ to MongoDB with id 67427ed9b98d7a37c043366a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_panda_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_panda_description/ to MongoDB with id 67427ed9b98d7a37c043366b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_fanuc_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_fanuc_moveit_config/ to MongoDB with id 67427edab98d7a37c043366c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources_fanuc_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources_fanuc_description/ to MongoDB with id 67427edab98d7a37c043366d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_resources/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_resources/ to MongoDB with id 67427edbb98d7a37c043366e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_py/ to MongoDB with id 67427edbb98d7a37c043366f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_plugins/ to MongoDB with id 67427edcb98d7a37c0433670\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_planners_stomp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_planners_stomp/ to MongoDB with id 67427edcb98d7a37c0433671\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_planners_ompl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_planners_ompl/ to MongoDB with id 67427eddb98d7a37c0433672\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_planners_chomp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_planners_chomp/ to MongoDB with id 67427eddb98d7a37c0433673\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_planners/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_planners/ to MongoDB with id 67427edeb98d7a37c0433674\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_msgs/ to MongoDB with id 67427edeb98d7a37c0433675\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_kinematics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_kinematics/ to MongoDB with id 67427edfb98d7a37c0433676\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_hybrid_planning/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_hybrid_planning/ to MongoDB with id 67427edfb98d7a37c0433677\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_core/ to MongoDB with id 67427ee0b98d7a37c0433678\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_configs_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_configs_utils/ to MongoDB with id 67427ee0b98d7a37c0433679\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit_common/ to MongoDB with id 67427ee0b98d7a37c043367a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/moveit/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/moveit/ to MongoDB with id 67427ee1b98d7a37c043367b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mouse_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mouse_teleop/ to MongoDB with id 67427ee1b98d7a37c043367c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/motion_capture_tracking_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/motion_capture_tracking_interfaces/ to MongoDB with id 67427ee2b98d7a37c043367d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/motion_capture_tracking/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/motion_capture_tracking/ to MongoDB with id 67427ee2b98d7a37c043367e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_yaml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_yaml/ to MongoDB with id 67427ee3b98d7a37c043367f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_viz/ to MongoDB with id 67427ee3b98d7a37c0433680\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_traj_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_traj_tools/ to MongoDB with id 67427ee4b98d7a37c0433681\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_test_datasets/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_test_datasets/ to MongoDB with id 67427ee4b98d7a37c0433682\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_relocalization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_relocalization/ to MongoDB with id 67427ee4b98d7a37c0433683\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_pose_list/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_pose_list/ to MongoDB with id 67427ee5b98d7a37c0433684\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_navstate_fuse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_navstate_fuse/ to MongoDB with id 67427ee5b98d7a37c0433685\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_navstate_fg/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_navstate_fg/ to MongoDB with id 67427ee6b98d7a37c0433686\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_msgs/ to MongoDB with id 67427ee6b98d7a37c0433687\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_metric_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_metric_maps/ to MongoDB with id 67427ee7b98d7a37c0433688\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_lidar_odometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_lidar_odometry/ to MongoDB with id 67427ee7b98d7a37c0433689\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_launcher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_launcher/ to MongoDB with id 67427ee8b98d7a37c043368a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_kernel/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_kernel/ to MongoDB with id 67427ee8b98d7a37c043368b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_rosbag2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_rosbag2/ to MongoDB with id 67427ee9b98d7a37c043368c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_ros2/ to MongoDB with id 67427ee9b98d7a37c043368d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_rawlog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_rawlog/ to MongoDB with id 67427eeab98d7a37c043368e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_paris_luco_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_paris_luco_dataset/ to MongoDB with id 67427eeab98d7a37c043368f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_mulran_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_mulran_dataset/ to MongoDB with id 67427eeab98d7a37c0433690\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_kitti_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_kitti_dataset/ to MongoDB with id 67427eebb98d7a37c0433691\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_kitti360_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_kitti360_dataset/ to MongoDB with id 67427eebb98d7a37c0433692\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_input_euroc_dataset/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_input_euroc_dataset/ to MongoDB with id 67427eecb98d7a37c0433693\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_imu_preintegration/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_imu_preintegration/ to MongoDB with id 67427eecb98d7a37c0433694\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_demos/ to MongoDB with id 67427eedb98d7a37c0433695\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_common/ to MongoDB with id 67427eedb98d7a37c0433696\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola_bridge_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola_bridge_ros2/ to MongoDB with id 67427eeeb98d7a37c0433697\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mola/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mola/ to MongoDB with id 67427eeeb98d7a37c0433698\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_robot/ to MongoDB with id 67427eeeb98d7a37c0433699\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_navigation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_navigation/ to MongoDB with id 67427eefb98d7a37c043369a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_msgs/ to MongoDB with id 67427eefb98d7a37c043369b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_gazebo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_gazebo/ to MongoDB with id 67427ef0b98d7a37c043369c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_dwb_critics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_dwb_critics/ to MongoDB with id 67427ef0b98d7a37c043369d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_driver/ to MongoDB with id 67427ef2b98d7a37c043369e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_description/ to MongoDB with id 67427ef2b98d7a37c043369f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mir_actions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mir_actions/ to MongoDB with id 67427ef2b98d7a37c04336a0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/microstrain_inertial_rqt/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/microstrain_inertial_rqt/ to MongoDB with id 67427ef3b98d7a37c04336a1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/microstrain_inertial_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/microstrain_inertial_msgs/ to MongoDB with id 67427ef3b98d7a37c04336a2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/microstrain_inertial_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/microstrain_inertial_examples/ to MongoDB with id 67427ef4b98d7a37c04336a3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/microstrain_inertial_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/microstrain_inertial_driver/ to MongoDB with id 67427ef4b98d7a37c04336a4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/microstrain_inertial_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/microstrain_inertial_description/ to MongoDB with id 67427ef5b98d7a37c04336a5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/micro_ros_diagnostic_updater/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/micro_ros_diagnostic_updater/ to MongoDB with id 67427ef5b98d7a37c04336a6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/micro_ros_diagnostic_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/micro_ros_diagnostic_bridge/ to MongoDB with id 67427ef6b98d7a37c04336a7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/metavision_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/metavision_driver/ to MongoDB with id 67427ef6b98d7a37c04336a8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/message_tf_frame_transformer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/message_tf_frame_transformer/ to MongoDB with id 67427ef7b98d7a37c04336a9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/message_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/message_filters/ to MongoDB with id 67427ef7b98d7a37c04336aa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/menge_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/menge_vendor/ to MongoDB with id 67427ef8b98d7a37c04336ab\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mcap_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mcap_vendor/ to MongoDB with id 67427ef8b98d7a37c04336ac\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mavros_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mavros_msgs/ to MongoDB with id 67427ef9b98d7a37c04336ad\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mavros_extras/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mavros_extras/ to MongoDB with id 67427ef9b98d7a37c04336ae\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mavros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mavros/ to MongoDB with id 67427efab98d7a37c04336af\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_visualization_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_visualization_msgs/ to MongoDB with id 67427efbb98d7a37c04336b0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_status_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_status_msgs/ to MongoDB with id 67427efbb98d7a37c04336b1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_sensor_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_sensor_msgs/ to MongoDB with id 67427efbb98d7a37c04336b2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_perception_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_perception_msgs/ to MongoDB with id 67427efcb98d7a37c04336b3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_nav_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_nav_msgs/ to MongoDB with id 67427efcb98d7a37c04336b4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_introspection_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_introspection_msgs/ to MongoDB with id 67427efdb98d7a37c04336b5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_dbw_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_dbw_msgs/ to MongoDB with id 67427efdb98d7a37c04336b6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_common_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_common_msgs/ to MongoDB with id 67427efeb98d7a37c04336b7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/marti_can_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/marti_can_msgs/ to MongoDB with id 67427efeb98d7a37c04336b8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mapviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mapviz_plugins/ to MongoDB with id 67427effb98d7a37c04336b9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mapviz_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mapviz_interfaces/ to MongoDB with id 67427effb98d7a37c04336ba\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/mapviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/mapviz/ to MongoDB with id 67427f00b98d7a37c04336bb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/magic_enum/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/magic_enum/ to MongoDB with id 67427f01b98d7a37c04336bc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/logging_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/logging_demo/ to MongoDB with id 67427f01b98d7a37c04336bd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/log_view/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/log_view/ to MongoDB with id 67427f02b98d7a37c04336be\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lifecycle_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lifecycle_py/ to MongoDB with id 67427f02b98d7a37c04336bf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lifecycle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lifecycle/ to MongoDB with id 67427f03b98d7a37c04336c0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lidar_situational_graphs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lidar_situational_graphs/ to MongoDB with id 67427f04b98d7a37c04336c1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libstatistics_collector/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libstatistics_collector/ to MongoDB with id 67427f04b98d7a37c04336c2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/librealsense2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/librealsense2/ to MongoDB with id 67427f05b98d7a37c04336c3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libpointmatcher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libpointmatcher/ to MongoDB with id 67427f06b98d7a37c04336c4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libnabo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libnabo/ to MongoDB with id 67427f06b98d7a37c04336c5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libmavconn/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libmavconn/ to MongoDB with id 67427f07b98d7a37c04336c6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libcurl_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libcurl_vendor/ to MongoDB with id 67427f07b98d7a37c04336c7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libcreate/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libcreate/ to MongoDB with id 67427f08b98d7a37c04336c8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libcaer_vendor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libcaer_vendor/ to MongoDB with id 67427f08b98d7a37c04336c9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/libcaer_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/libcaer_driver/ to MongoDB with id 67427f09b98d7a37c04336ca\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_teleop/ to MongoDB with id 67427f0ab98d7a37c04336cb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_simulator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_simulator/ to MongoDB with id 67427f0bb98d7a37c04336cc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_msgs/ to MongoDB with id 67427f0bb98d7a37c04336cd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_gz_worlds/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_gz_worlds/ to MongoDB with id 67427f0cb98d7a37c04336ce\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_gz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_gz_plugins/ to MongoDB with id 67427f0cb98d7a37c04336cf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_gz_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_gz_bringup/ to MongoDB with id 67427f0cb98d7a37c04336d0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo_description/ to MongoDB with id 67427f0db98d7a37c04336d1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/leo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/leo/ to MongoDB with id 67427f0db98d7a37c04336d2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_yaml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_yaml/ to MongoDB with id 67427f0eb98d7a37c04336d3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_xml/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_xml/ to MongoDB with id 67427f0eb98d7a37c04336d4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_testing_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_testing_ros/ to MongoDB with id 67427f0fb98d7a37c04336d5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_testing_ament_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_testing_ament_cmake/ to MongoDB with id 67427f0fb98d7a37c04336d6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_testing/ to MongoDB with id 67427f10b98d7a37c04336d7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_system_modes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_system_modes/ to MongoDB with id 67427f10b98d7a37c04336d8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_ros/ to MongoDB with id 67427f11b98d7a37c04336d9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_pytest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_pytest/ to MongoDB with id 67427f11b98d7a37c04336da\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch_param_builder/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch_param_builder/ to MongoDB with id 67427f12b98d7a37c04336db\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/launch/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/launch/ to MongoDB with id 67427f12b98d7a37c04336dc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/laser_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/laser_proc/ to MongoDB with id 67427f13b98d7a37c04336dd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/laser_geometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/laser_geometry/ to MongoDB with id 67427f13b98d7a37c04336de\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_validation/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_validation/ to MongoDB with id 67427f14b98d7a37c04336df\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_traffic_rules/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_traffic_rules/ to MongoDB with id 67427f14b98d7a37c04336e0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_routing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_routing/ to MongoDB with id 67427f15b98d7a37c04336e1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_python/ to MongoDB with id 67427f15b98d7a37c04336e2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_projection/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_projection/ to MongoDB with id 67427f16b98d7a37c04336e3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_matching/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_matching/ to MongoDB with id 67427f16b98d7a37c04336e4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_maps/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_maps/ to MongoDB with id 67427f17b98d7a37c04336e5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_io/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_io/ to MongoDB with id 67427f17b98d7a37c04336e6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_examples/ to MongoDB with id 67427f18b98d7a37c04336e7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2_core/ to MongoDB with id 67427f18b98d7a37c04336e8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/lanelet2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/lanelet2/ to MongoDB with id 67427f18b98d7a37c04336e9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kortex_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kortex_driver/ to MongoDB with id 67427f19b98d7a37c04336ea\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kortex_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kortex_description/ to MongoDB with id 67427f1ab98d7a37c04336eb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kortex_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kortex_bringup/ to MongoDB with id 67427f1ab98d7a37c04336ec\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kortex_api/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kortex_api/ to MongoDB with id 67427f1ab98d7a37c04336ed\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kobuki_velocity_smoother/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kobuki_velocity_smoother/ to MongoDB with id 67427f1bb98d7a37c04336ee\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kobuki_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kobuki_core/ to MongoDB with id 67427f1bb98d7a37c04336ef\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kitti_metrics_eval/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kitti_metrics_eval/ to MongoDB with id 67427f1cb98d7a37c04336f0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kinova_gen3_lite_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kinova_gen3_lite_moveit_config/ to MongoDB with id 67427f1cb98d7a37c04336f1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kinova_gen3_7dof_robotiq_2f_85_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kinova_gen3_7dof_robotiq_2f_85_moveit_config/ to MongoDB with id 67427f1db98d7a37c04336f2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kinova_gen3_6dof_robotiq_2f_85_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kinova_gen3_6dof_robotiq_2f_85_moveit_config/ to MongoDB with id 67427f1eb98d7a37c04336f3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kinematics_interface_kdl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kinematics_interface_kdl/ to MongoDB with id 67427f1eb98d7a37c04336f4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kinematics_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kinematics_interface/ to MongoDB with id 67427f1fb98d7a37c04336f5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/keyboard_handler/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/keyboard_handler/ to MongoDB with id 67427f20b98d7a37c04336f6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/key_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/key_teleop/ to MongoDB with id 67427f20b98d7a37c04336f7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/kdl_parser/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/kdl_parser/ to MongoDB with id 67427f21b98d7a37c04336f8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joy_tester/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joy_tester/ to MongoDB with id 67427f21b98d7a37c04336f9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joy_teleop/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joy_teleop/ to MongoDB with id 67427f21b98d7a37c04336fa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joy/ to MongoDB with id 67427f22b98d7a37c04336fb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joint_trajectory_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joint_trajectory_controller/ to MongoDB with id 67427f22b98d7a37c04336fc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joint_state_publisher_gui/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joint_state_publisher_gui/ to MongoDB with id 67427f23b98d7a37c04336fd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joint_state_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joint_state_publisher/ to MongoDB with id 67427f23b98d7a37c04336fe\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joint_state_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joint_state_broadcaster/ to MongoDB with id 67427f24b98d7a37c04336ff\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/joint_limits/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/joint_limits/ to MongoDB with id 67427f24b98d7a37c0433700\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/io_context/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/io_context/ to MongoDB with id 67427f25b98d7a37c0433701\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/intra_process_demo/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/intra_process_demo/ to MongoDB with id 67427f26b98d7a37c0433702\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/interactive_markers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/interactive_markers/ to MongoDB with id 67427f26b98d7a37c0433703\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/interactive_marker_twist_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/interactive_marker_twist_server/ to MongoDB with id 67427f27b98d7a37c0433704\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/imu_transformer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/imu_transformer/ to MongoDB with id 67427f27b98d7a37c0433705\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/imu_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/imu_tools/ to MongoDB with id 67427f28b98d7a37c0433706\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/imu_sensor_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/imu_sensor_broadcaster/ to MongoDB with id 67427f28b98d7a37c0433707\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/imu_filter_madgwick/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/imu_filter_madgwick/ to MongoDB with id 67427f29b98d7a37c0433708\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/imu_complementary_filter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/imu_complementary_filter/ to MongoDB with id 67427f29b98d7a37c0433709\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_view/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_view/ to MongoDB with id 67427f2ab98d7a37c043370a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_transport_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_transport_plugins/ to MongoDB with id 67427f2ab98d7a37c043370b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_transport/ to MongoDB with id 67427f2bb98d7a37c043370c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_tools/ to MongoDB with id 67427f2cb98d7a37c043370d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_rotate/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_rotate/ to MongoDB with id 67427f2cb98d7a37c043370e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_publisher/ to MongoDB with id 67427f2db98d7a37c043370f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_proc/ to MongoDB with id 67427f2db98d7a37c0433710\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_pipeline/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_pipeline/ to MongoDB with id 67427f2eb98d7a37c0433711\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/image_geometry/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/image_geometry/ to MongoDB with id 67427f2fb98d7a37c0433712\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ign_rviz_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ign_rviz_common/ to MongoDB with id 67427f30b98d7a37c0433713\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/hpp-fcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/hpp-fcl/ to MongoDB with id 67427f30b98d7a37c0433714\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/hls_lfcd_lds_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/hls_lfcd_lds_driver/ to MongoDB with id 67427f31b98d7a37c0433715\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/heaphook/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/heaphook/ to MongoDB with id 67427f31b98d7a37c0433716\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/hatchbed_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/hatchbed_common/ to MongoDB with id 67427f32b98d7a37c0433717\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/hardware_interface_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/hardware_interface_testing/ to MongoDB with id 67427f32b98d7a37c0433718\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/hardware_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/hardware_interface/ to MongoDB with id 67427f33b98d7a37c0433719\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gz_ros2_control_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gz_ros2_control_tests/ to MongoDB with id 67427f33b98d7a37c043371a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gz_ros2_control_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gz_ros2_control_demos/ to MongoDB with id 67427f34b98d7a37c043371b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gz_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gz_ros2_control/ to MongoDB with id 67427f34b98d7a37c043371c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gurumdds_cmake_module/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gurumdds_cmake_module/ to MongoDB with id 67427f35b98d7a37c043371d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gtsam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gtsam/ to MongoDB with id 67427f35b98d7a37c043371e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gscam/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gscam/ to MongoDB with id 67427f35b98d7a37c043371f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gripper_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gripper_controllers/ to MongoDB with id 67427f36b98d7a37c0433720\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_visualization/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_visualization/ to MongoDB with id 67427f37b98d7a37c0433721\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_sdf/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_sdf/ to MongoDB with id 67427f37b98d7a37c0433722\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_rviz_plugin/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_rviz_plugin/ to MongoDB with id 67427f38b98d7a37c0433723\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_ros/ to MongoDB with id 67427f38b98d7a37c0433724\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_pcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_pcl/ to MongoDB with id 67427f39b98d7a37c0433725\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_octomap/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_octomap/ to MongoDB with id 67427f39b98d7a37c0433726\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_msgs/ to MongoDB with id 67427f3ab98d7a37c0433727\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_loader/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_loader/ to MongoDB with id 67427f3ab98d7a37c0433728\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_filters/ to MongoDB with id 67427f3ab98d7a37c0433729\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_demos/ to MongoDB with id 67427f3bb98d7a37c043372a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_cv/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_cv/ to MongoDB with id 67427f3cb98d7a37c043372b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_costmap_2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_costmap_2d/ to MongoDB with id 67427f3cb98d7a37c043372c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_core/ to MongoDB with id 67427f3db98d7a37c043372d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map_cmake_helpers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map_cmake_helpers/ to MongoDB with id 67427f3db98d7a37c043372e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grid_map/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grid_map/ to MongoDB with id 67427f3db98d7a37c043372f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grbl_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grbl_ros/ to MongoDB with id 67427f3eb98d7a37c0433730\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/grasping_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/grasping_msgs/ to MongoDB with id 67427f3eb98d7a37c0433731\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gpsd_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gpsd_client/ to MongoDB with id 67427f3fb98d7a37c0433732\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gps_umd/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gps_umd/ to MongoDB with id 67427f3fb98d7a37c0433733\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gps_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gps_tools/ to MongoDB with id 67427f40b98d7a37c0433734\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gps_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gps_msgs/ to MongoDB with id 67427f40b98d7a37c0433735\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/geometry_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/geometry_tutorials/ to MongoDB with id 67427f41b98d7a37c0433736\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/geometry_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/geometry_msgs/ to MongoDB with id 67427f41b98d7a37c0433737\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/geometry2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/geometry2/ to MongoDB with id 67427f42b98d7a37c0433738\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/geometric_shapes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/geometric_shapes/ to MongoDB with id 67427f42b98d7a37c0433739\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/generate_parameter_module_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/generate_parameter_module_example/ to MongoDB with id 67427f43b98d7a37c043373a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/generate_parameter_library_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/generate_parameter_library_py/ to MongoDB with id 67427f43b98d7a37c043373b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/generate_parameter_library_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/generate_parameter_library_example/ to MongoDB with id 67427f44b98d7a37c043373c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/generate_parameter_library/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/generate_parameter_library/ to MongoDB with id 67427f44b98d7a37c043373d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gc_spl_2022/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gc_spl_2022/ to MongoDB with id 67427f45b98d7a37c043373e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gc_spl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gc_spl/ to MongoDB with id 67427f45b98d7a37c043373f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_video_monitor_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_video_monitor_utils/ to MongoDB with id 67427f45b98d7a37c0433740\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_ros_pkgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_ros_pkgs/ to MongoDB with id 67427f46b98d7a37c0433741\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_ros2_control_demos/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_ros2_control_demos/ to MongoDB with id 67427f47b98d7a37c0433742\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_ros2_control/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_ros2_control/ to MongoDB with id 67427f47b98d7a37c0433743\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_ros/ to MongoDB with id 67427f48b98d7a37c0433744\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_msgs/ to MongoDB with id 67427f48b98d7a37c0433745\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/gazebo_dev/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/gazebo_dev/ to MongoDB with id 67427f49b98d7a37c0433746\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/game_controller_spl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/game_controller_spl/ to MongoDB with id 67427f49b98d7a37c0433747\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_viz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_viz/ to MongoDB with id 67427f49b98d7a37c0433748\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_variables/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_variables/ to MongoDB with id 67427f4ab98d7a37c0433749\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_tutorials/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_tutorials/ to MongoDB with id 67427f4bb98d7a37c043374a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_publishers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_publishers/ to MongoDB with id 67427f4bb98d7a37c043374b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_optimizers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_optimizers/ to MongoDB with id 67427f4cb98d7a37c043374c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_msgs/ to MongoDB with id 67427f4cb98d7a37c043374d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_models/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_models/ to MongoDB with id 67427f4cb98d7a37c043374e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_loss/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_loss/ to MongoDB with id 67427f4db98d7a37c043374f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_graphs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_graphs/ to MongoDB with id 67427f4db98d7a37c0433750\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_doc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_doc/ to MongoDB with id 67427f4eb98d7a37c0433751\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_core/ to MongoDB with id 67427f4fb98d7a37c0433752\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse_constraints/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse_constraints/ to MongoDB with id 67427f4fb98d7a37c0433753\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fuse/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fuse/ to MongoDB with id 67427f4fb98d7a37c0433754\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/foxglove_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/foxglove_msgs/ to MongoDB with id 67427f50b98d7a37c0433755\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/foxglove_compressed_video_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/foxglove_compressed_video_transport/ to MongoDB with id 67427f50b98d7a37c0433756\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/foxglove_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/foxglove_bridge/ to MongoDB with id 67427f51b98d7a37c0433757\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/forward_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/forward_local_planner/ to MongoDB with id 67427f52b98d7a37c0433758\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/forward_global_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/forward_global_planner/ to MongoDB with id 67427f52b98d7a37c0433759\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/forward_command_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/forward_command_controller/ to MongoDB with id 67427f53b98d7a37c043375a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/force_torque_sensor_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/force_torque_sensor_broadcaster/ to MongoDB with id 67427f53b98d7a37c043375b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fmi_adapter/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fmi_adapter/ to MongoDB with id 67427f54b98d7a37c043375c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fluent_rviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fluent_rviz/ to MongoDB with id 67427f55b98d7a37c043375d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flir_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flir_camera_msgs/ to MongoDB with id 67427f56b98d7a37c043375e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flir_camera_description/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flir_camera_description/ to MongoDB with id 67427f56b98d7a37c043375f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_widget/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_widget/ to MongoDB with id 67427f57b98d7a37c0433760\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_testing/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_testing/ to MongoDB with id 67427f57b98d7a37c0433761\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_states/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_states/ to MongoDB with id 67427f58b98d7a37c0433762\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_onboard/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_onboard/ to MongoDB with id 67427f58b98d7a37c0433763\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_msgs/ to MongoDB with id 67427f59b98d7a37c0433764\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_mirror/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_mirror/ to MongoDB with id 67427f59b98d7a37c0433765\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_input/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_input/ to MongoDB with id 67427f5ab98d7a37c0433766\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_core/ to MongoDB with id 67427f5ab98d7a37c0433767\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flexbe_behavior_engine/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flexbe_behavior_engine/ to MongoDB with id 67427f5bb98d7a37c0433768\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/flex_sync/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/flex_sync/ to MongoDB with id 67427f5bb98d7a37c0433769\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/find_object_2d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/find_object_2d/ to MongoDB with id 67427f5cb98d7a37c043376a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/filters/ to MongoDB with id 67427f5cb98d7a37c043376b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fields2cover/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fields2cover/ to MongoDB with id 67427f5db98d7a37c043376c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ffmpeg_encoder_decoder/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ffmpeg_encoder_decoder/ to MongoDB with id 67427f5db98d7a37c043376d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/fast_gicp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/fast_gicp/ to MongoDB with id 67427f5eb98d7a37c043376e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/executive_smach/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/executive_smach/ to MongoDB with id 67427f5eb98d7a37c043376f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_tf2_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_tf2_py/ to MongoDB with id 67427f5fb98d7a37c0433770\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_pointcloud_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_pointcloud_publisher/ to MongoDB with id 67427f60b98d7a37c0433771\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_minimal_subscriber/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_minimal_subscriber/ to MongoDB with id 67427f60b98d7a37c0433772\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_minimal_service/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_minimal_service/ to MongoDB with id 67427f61b98d7a37c0433773\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_minimal_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_minimal_publisher/ to MongoDB with id 67427f61b98d7a37c0433774\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_minimal_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_minimal_client/ to MongoDB with id 67427f61b98d7a37c0433775\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_minimal_action_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_minimal_action_server/ to MongoDB with id 67427f62b98d7a37c0433776\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_minimal_action_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_minimal_action_client/ to MongoDB with id 67427f62b98d7a37c0433777\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_guard_conditions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_guard_conditions/ to MongoDB with id 67427f63b98d7a37c0433778\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclpy_executors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclpy_executors/ to MongoDB with id 67427f63b98d7a37c0433779\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_wait_set/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_wait_set/ to MongoDB with id 67427f64b98d7a37c043377a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_multithreaded_executor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_multithreaded_executor/ to MongoDB with id 67427f64b98d7a37c043377b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_timer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_timer/ to MongoDB with id 67427f65b98d7a37c043377c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_subscriber/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_subscriber/ to MongoDB with id 67427f65b98d7a37c043377d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_service/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_service/ to MongoDB with id 67427f66b98d7a37c043377e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_publisher/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_publisher/ to MongoDB with id 67427f66b98d7a37c043377f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_composition/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_composition/ to MongoDB with id 67427f67b98d7a37c0433780\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_client/ to MongoDB with id 67427f67b98d7a37c0433781\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_action_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_action_server/ to MongoDB with id 67427f67b98d7a37c0433782\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_action_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_minimal_action_client/ to MongoDB with id 67427f68b98d7a37c0433783\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_cbg_executor/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_cbg_executor/ to MongoDB with id 67427f68b98d7a37c0433784\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/examples_rclcpp_async_client/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/examples_rclcpp_async_client/ to MongoDB with id 67427f69b98d7a37c0433785\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/event_camera_renderer/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/event_camera_renderer/ to MongoDB with id 67427f69b98d7a37c0433786\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/event_camera_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/event_camera_py/ to MongoDB with id 67427f69b98d7a37c0433787\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/event_camera_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/event_camera_msgs/ to MongoDB with id 67427f6ab98d7a37c0433788\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/event_camera_codecs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/event_camera_codecs/ to MongoDB with id 67427f6ab98d7a37c0433789\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_vam_ts_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_vam_ts_msgs/ to MongoDB with id 67427f6bb98d7a37c043378a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_vam_ts_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_vam_ts_conversion/ to MongoDB with id 67427f6bb98d7a37c043378b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_vam_ts_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_vam_ts_coding/ to MongoDB with id 67427f6cb98d7a37c043378c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_rviz_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_rviz_plugins/ to MongoDB with id 67427f6cb98d7a37c043378d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_primitives_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_primitives_conversion/ to MongoDB with id 67427f6db98d7a37c043378e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_msgs_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_msgs_utils/ to MongoDB with id 67427f6db98d7a37c043378f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_msgs/ to MongoDB with id 67427f6db98d7a37c0433790\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_messages/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_messages/ to MongoDB with id 67427f6eb98d7a37c0433791\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_denm_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_denm_msgs/ to MongoDB with id 67427f6eb98d7a37c0433792\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_denm_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_denm_conversion/ to MongoDB with id 67427f6fb98d7a37c0433793\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_denm_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_denm_coding/ to MongoDB with id 67427f6fb98d7a37c0433794\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cpm_ts_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cpm_ts_msgs/ to MongoDB with id 67427f70b98d7a37c0433795\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cpm_ts_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cpm_ts_conversion/ to MongoDB with id 67427f70b98d7a37c0433796\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cpm_ts_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cpm_ts_coding/ to MongoDB with id 67427f71b98d7a37c0433797\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_conversion/ to MongoDB with id 67427f72b98d7a37c0433798\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_coding/ to MongoDB with id 67427f72b98d7a37c0433799\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cam_ts_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cam_ts_msgs/ to MongoDB with id 67427f73b98d7a37c043379a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cam_ts_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cam_ts_conversion/ to MongoDB with id 67427f73b98d7a37c043379b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cam_ts_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cam_ts_coding/ to MongoDB with id 67427f74b98d7a37c043379c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cam_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cam_msgs/ to MongoDB with id 67427f75b98d7a37c043379d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cam_conversion/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cam_conversion/ to MongoDB with id 67427f75b98d7a37c043379e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/etsi_its_cam_coding/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/etsi_its_cam_coding/ to MongoDB with id 67427f76b98d7a37c043379f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/eiquadprog/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/eiquadprog/ to MongoDB with id 67427f76b98d7a37c04337a0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/eigenpy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/eigenpy/ to MongoDB with id 67427f77b98d7a37c04337a1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/eigen_stl_containers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/eigen_stl_containers/ to MongoDB with id 67427f78b98d7a37c04337a2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/effort_controllers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/effort_controllers/ to MongoDB with id 67427f78b98d7a37c04337a3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_utilities/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_utilities/ to MongoDB with id 67427f79b98d7a37c04337a4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_time_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_time_lite/ to MongoDB with id 67427f79b98d7a37c04337a5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_time/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_time/ to MongoDB with id 67427f7ab98d7a37c04337a6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_threads/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_threads/ to MongoDB with id 67427f7ab98d7a37c04337a7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_streams/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_streams/ to MongoDB with id 67427f7bb98d7a37c04337a8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_sigslots_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_sigslots_lite/ to MongoDB with id 67427f7bb98d7a37c04337a9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_sigslots/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_sigslots/ to MongoDB with id 67427f7cb98d7a37c04337aa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_mpl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_mpl/ to MongoDB with id 67427f7cb98d7a37c04337ab\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_mobile_robot/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_mobile_robot/ to MongoDB with id 67427f7db98d7a37c04337ac\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_math/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_math/ to MongoDB with id 67427f7eb98d7a37c04337ad\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_lite/ to MongoDB with id 67427f7fb98d7a37c04337ae\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_linear_algebra/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_linear_algebra/ to MongoDB with id 67427f80b98d7a37c04337af\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_ipc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_ipc/ to MongoDB with id 67427f80b98d7a37c04337b0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_io/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_io/ to MongoDB with id 67427f81b98d7a37c04337b1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_formatters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_formatters/ to MongoDB with id 67427f81b98d7a37c04337b2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_filesystem/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_filesystem/ to MongoDB with id 67427f82b98d7a37c04337b3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_exceptions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_exceptions/ to MongoDB with id 67427f82b98d7a37c04337b4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_errors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_errors/ to MongoDB with id 67427f83b98d7a37c04337b5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_eigen/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_eigen/ to MongoDB with id 67427f83b98d7a37c04337b6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_devices/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_devices/ to MongoDB with id 67427f84b98d7a37c04337b7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_converters_lite/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_converters_lite/ to MongoDB with id 67427f84b98d7a37c04337b8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_console/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_console/ to MongoDB with id 67427f86b98d7a37c04337b9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_config/ to MongoDB with id 67427f86b98d7a37c04337ba\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_concepts/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_concepts/ to MongoDB with id 67427f87b98d7a37c04337bb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecl_command_line/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecl_command_line/ to MongoDB with id 67427f88b98d7a37c04337bc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ecal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ecal/ to MongoDB with id 67427f88b98d7a37c04337bd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dynamixel_workbench_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dynamixel_workbench_toolbox/ to MongoDB with id 67427f89b98d7a37c04337be\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dynamixel_sdk_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dynamixel_sdk_examples/ to MongoDB with id 67427f89b98d7a37c04337bf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dynamixel_sdk/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dynamixel_sdk/ to MongoDB with id 67427f8bb98d7a37c04337c0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dynamixel_hardware/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dynamixel_hardware/ to MongoDB with id 67427f8bb98d7a37c04337c1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dynamic_edt_3d/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dynamic_edt_3d/ to MongoDB with id 67427f8cb98d7a37c04337c2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dwb_plugins/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dwb_plugins/ to MongoDB with id 67427f8cb98d7a37c04337c3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dwb_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dwb_msgs/ to MongoDB with id 67427f8db98d7a37c04337c4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dwb_critics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dwb_critics/ to MongoDB with id 67427f8db98d7a37c04337c5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dwb_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dwb_core/ to MongoDB with id 67427f8eb98d7a37c04337c6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dummy_sensors/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dummy_sensors/ to MongoDB with id 67427f8eb98d7a37c04337c7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dummy_robot_bringup/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dummy_robot_bringup/ to MongoDB with id 67427f8fb98d7a37c04337c8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dummy_map_server/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dummy_map_server/ to MongoDB with id 67427f8fb98d7a37c04337c9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/dual_arm_panda_moveit_config/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/dual_arm_panda_moveit_config/ to MongoDB with id 67427f90b98d7a37c04337ca\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/draco_point_cloud_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/draco_point_cloud_transport/ to MongoDB with id 67427f90b98d7a37c04337cb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/domain_coordinator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/domain_coordinator/ to MongoDB with id 67427f90b98d7a37c04337cc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/domain_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/domain_bridge/ to MongoDB with id 67427f91b98d7a37c04337cd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/diff_drive_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/diff_drive_controller/ to MongoDB with id 67427f92b98d7a37c04337ce\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/diagnostics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/diagnostics/ to MongoDB with id 67427f92b98d7a37c04337cf\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/diagnostic_updater/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/diagnostic_updater/ to MongoDB with id 67427f92b98d7a37c04337d0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/diagnostic_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/diagnostic_msgs/ to MongoDB with id 67427f93b98d7a37c04337d1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/diagnostic_common_diagnostics/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/diagnostic_common_diagnostics/ to MongoDB with id 67427f93b98d7a37c04337d2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/diagnostic_aggregator/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/diagnostic_aggregator/ to MongoDB with id 67427f94b98d7a37c04337d3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthimage_to_laserscan/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthimage_to_laserscan/ to MongoDB with id 67427f95b98d7a37c04337d4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai_ros_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai_ros_msgs/ to MongoDB with id 67427f95b98d7a37c04337d5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai_ros_driver/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai_ros_driver/ to MongoDB with id 67427f96b98d7a37c04337d6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai_filters/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai_filters/ to MongoDB with id 67427f96b98d7a37c04337d7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai_examples/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai_examples/ to MongoDB with id 67427f97b98d7a37c04337d8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai_descriptions/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai_descriptions/ to MongoDB with id 67427f97b98d7a37c04337d9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai_bridge/ to MongoDB with id 67427f98b98d7a37c04337da\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai/ to MongoDB with id 67427f98b98d7a37c04337db\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depthai-ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depthai-ros/ to MongoDB with id 67427f99b98d7a37c04337dc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/depth_image_proc/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/depth_image_proc/ to MongoDB with id 67427f99b98d7a37c04337dd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/demo_nodes_py/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/demo_nodes_py/ to MongoDB with id 67427f9ab98d7a37c04337de\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/demo_nodes_cpp_native/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/demo_nodes_cpp_native/ to MongoDB with id 67427f9ab98d7a37c04337df\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/demo_nodes_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/demo_nodes_cpp/ to MongoDB with id 67427f9bb98d7a37c04337e0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/cyclonedds/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/cyclonedds/ to MongoDB with id 67427f9cb98d7a37c04337e1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/costmap_queue/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/costmap_queue/ to MongoDB with id 67427f9cb98d7a37c04337e2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/controller_manager_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/controller_manager_msgs/ to MongoDB with id 67427f9db98d7a37c04337e3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/controller_manager/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/controller_manager/ to MongoDB with id 67427f9db98d7a37c04337e4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/controller_interface/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/controller_interface/ to MongoDB with id 67427f9eb98d7a37c04337e5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/control_toolbox/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/control_toolbox/ to MongoDB with id 67427f9fb98d7a37c04337e6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/control_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/control_msgs/ to MongoDB with id 67427f9fb98d7a37c04337e7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/compressed_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/compressed_image_transport/ to MongoDB with id 67427fa0b98d7a37c04337e8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/compressed_depth_image_transport/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/compressed_depth_image_transport/ to MongoDB with id 67427fa0b98d7a37c04337e9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/composition/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/composition/ to MongoDB with id 67427fa1b98d7a37c04337ea\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/common_interfaces/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/common_interfaces/ to MongoDB with id 67427fa1b98d7a37c04337eb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/color_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/color_util/ to MongoDB with id 67427fa2b98d7a37c04337ec\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/color_names/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/color_names/ to MongoDB with id 67427fa2b98d7a37c04337ed\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/coal/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/coal/ to MongoDB with id 67427fa3b98d7a37c04337ee\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/cmake_generate_parameter_module_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/cmake_generate_parameter_module_example/ to MongoDB with id 67427fa4b98d7a37c04337ef\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/classic_bags/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/classic_bags/ to MongoDB with id 67427fa4b98d7a37c04337f0\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/class_loader/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/class_loader/ to MongoDB with id 67427fa6b98d7a37c04337f1\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/chomp_motion_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/chomp_motion_planner/ to MongoDB with id 67427fa6b98d7a37c04337f2\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/catch_ros2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/catch_ros2/ to MongoDB with id 67427fa7b98d7a37c04337f3\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/cartographer_rviz/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/cartographer_rviz/ to MongoDB with id 67427fa8b98d7a37c04337f4\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/cartographer_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/cartographer_ros/ to MongoDB with id 67427fa9b98d7a37c04337f5\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/camera_calibration_parsers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/camera_calibration_parsers/ to MongoDB with id 67427faab98d7a37c04337f6\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/camera_aravis2_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/camera_aravis2_msgs/ to MongoDB with id 67427faab98d7a37c04337f7\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/camera_aravis2/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/camera_aravis2/ to MongoDB with id 67427faab98d7a37c04337f8\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bosch_locator_bridge_utils/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bosch_locator_bridge_utils/ to MongoDB with id 67427fabb98d7a37c04337f9\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bosch_locator_bridge/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bosch_locator_bridge/ to MongoDB with id 67427facb98d7a37c04337fa\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/boost_geometry_util/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/boost_geometry_util/ to MongoDB with id 67427facb98d7a37c04337fb\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bondpy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bondpy/ to MongoDB with id 67427fadb98d7a37c04337fc\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bondcpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bondcpp/ to MongoDB with id 67427fadb98d7a37c04337fd\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bond_core/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bond_core/ to MongoDB with id 67427faeb98d7a37c04337fe\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bond/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bond/ to MongoDB with id 67427faeb98d7a37c04337ff\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bno055/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bno055/ to MongoDB with id 67427fafb98d7a37c0433800\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bicycle_steering_controller/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bicycle_steering_controller/ to MongoDB with id 67427fafb98d7a37c0433801\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_tutorial/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_tutorial/ to MongoDB with id 67427fb0b98d7a37c0433802\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_tools/ to MongoDB with id 67427fb0b98d7a37c0433803\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_system_tests/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_system_tests/ to MongoDB with id 67427fb0b98d7a37c0433804\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_ros/ to MongoDB with id 67427fb1b98d7a37c0433805\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_example/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_example/ to MongoDB with id 67427fb1b98d7a37c0433806\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_benchmark/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_benchmark/ to MongoDB with id 67427fb2b98d7a37c0433807\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga_amcl/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga_amcl/ to MongoDB with id 67427fb2b98d7a37c0433808\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/beluga/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/beluga/ to MongoDB with id 67427fb3b98d7a37c0433809\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/behaviortree_cpp_v3/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/behaviortree_cpp_v3/ to MongoDB with id 67427fb3b98d7a37c043380a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/behaviortree_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/behaviortree_cpp/ to MongoDB with id 67427fb4b98d7a37c043380b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/battery_state_rviz_overlay/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/battery_state_rviz_overlay/ to MongoDB with id 67427fb4b98d7a37c043380c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/battery_state_broadcaster/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/battery_state_broadcaster/ to MongoDB with id 67427fb5b98d7a37c043380d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/bag2_to_image/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/bag2_to_image/ to MongoDB with id 67427fb5b98d7a37c043380e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/backward_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/backward_ros/ to MongoDB with id 67427fb6b98d7a37c043380f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/backward_local_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/backward_local_planner/ to MongoDB with id 67427fb6b98d7a37c0433810\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/backward_global_planner/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/backward_global_planner/ to MongoDB with id 67427fb7b98d7a37c0433811\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/automotive_platform_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/automotive_platform_msgs/ to MongoDB with id 67427fb7b98d7a37c0433812\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/automotive_navigation_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/automotive_navigation_msgs/ to MongoDB with id 67427fb8b98d7a37c0433813\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/automotive_autonomy_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/automotive_autonomy_msgs/ to MongoDB with id 67427fb8b98d7a37c0433814\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/async_web_server_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/async_web_server_cpp/ to MongoDB with id 67427fb9b98d7a37c0433815\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/aruco_ros/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/aruco_ros/ to MongoDB with id 67427fb9b98d7a37c0433816\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/aruco_opencv_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/aruco_opencv_msgs/ to MongoDB with id 67427fbab98d7a37c0433817\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/aruco_opencv/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/aruco_opencv/ to MongoDB with id 67427fbab98d7a37c0433818\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/aruco_msgs/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/aruco_msgs/ to MongoDB with id 67427fbab98d7a37c0433819\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/aruco/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/aruco/ to MongoDB with id 67427fbbb98d7a37c043381a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apriltag_draw/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apriltag_draw/ to MongoDB with id 67427fbcb98d7a37c043381b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apriltag_detector_umich/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apriltag_detector_umich/ to MongoDB with id 67427fbcb98d7a37c043381c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apriltag_detector_mit/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apriltag_detector_mit/ to MongoDB with id 67427fbdb98d7a37c043381d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apriltag_detector/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apriltag_detector/ to MongoDB with id 67427fbdb98d7a37c043381e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apriltag/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apriltag/ to MongoDB with id 67427fbeb98d7a37c043381f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apex_test_tools/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apex_test_tools/ to MongoDB with id 67427fbeb98d7a37c0433820\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/apex_containers/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/apex_containers/ to MongoDB with id 67427fbfb98d7a37c0433821\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/angles/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/angles/ to MongoDB with id 67427fc0b98d7a37c0433822\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_xmllint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_xmllint/ to MongoDB with id 67427fc0b98d7a37c0433823\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_uncrustify/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_uncrustify/ to MongoDB with id 67427fc1b98d7a37c0433824\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_pyflakes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_pyflakes/ to MongoDB with id 67427fc1b98d7a37c0433825\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_pycodestyle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_pycodestyle/ to MongoDB with id 67427fc2b98d7a37c0433826\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_pep257/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_pep257/ to MongoDB with id 67427fc2b98d7a37c0433827\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_pclint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_pclint/ to MongoDB with id 67427fc3b98d7a37c0433828\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_package/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_package/ to MongoDB with id 67427fc3b98d7a37c0433829\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_mypy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_mypy/ to MongoDB with id 67427fc4b98d7a37c043382a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_lint_common/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_lint_common/ to MongoDB with id 67427fc4b98d7a37c043382b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_lint_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_lint_cmake/ to MongoDB with id 67427fc5b98d7a37c043382c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_lint_auto/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_lint_auto/ to MongoDB with id 67427fc5b98d7a37c043382d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_lint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_lint/ to MongoDB with id 67427fc6b98d7a37c043382e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_index_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_index_python/ to MongoDB with id 67427fc6b98d7a37c043382f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_index_cpp/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_index_cpp/ to MongoDB with id 67427fc7b98d7a37c0433830\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_flake8/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_flake8/ to MongoDB with id 67427fc8b98d7a37c0433831\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cpplint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cpplint/ to MongoDB with id 67427fc9b98d7a37c0433832\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cppcheck/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cppcheck/ to MongoDB with id 67427fc9b98d7a37c0433833\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_copyright/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_copyright/ to MongoDB with id 67427fcab98d7a37c0433834\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_xmllint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_xmllint/ to MongoDB with id 67427fcab98d7a37c0433835\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_version/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_version/ to MongoDB with id 67427fcbb98d7a37c0433836\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_vendor_package/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_vendor_package/ to MongoDB with id 67427fcbb98d7a37c0433837\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_uncrustify/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_uncrustify/ to MongoDB with id 67427fcbb98d7a37c0433838\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_test/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_test/ to MongoDB with id 67427fccb98d7a37c0433839\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_target_dependencies/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_target_dependencies/ to MongoDB with id 67427fccb98d7a37c043383a\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_python/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_python/ to MongoDB with id 67427fcdb98d7a37c043383b\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_pytest/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_pytest/ to MongoDB with id 67427fcdb98d7a37c043383c\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_pyflakes/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_pyflakes/ to MongoDB with id 67427fceb98d7a37c043383d\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_pycodestyle/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_pycodestyle/ to MongoDB with id 67427fceb98d7a37c043383e\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_pep257/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_pep257/ to MongoDB with id 67427fcfb98d7a37c043383f\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_pclint/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_pclint/ to MongoDB with id 67427fcfb98d7a37c0433840\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_mypy/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_mypy/ to MongoDB with id 67427fd0b98d7a37c0433841\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_lint_cmake/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_lint_cmake/ to MongoDB with id 67427fd0b98d7a37c0433842\n", + "\n", + "Scraping https://docs.ros.org/en/iron/p/ament_cmake_libraries/ (Depth: 5)\n", + "Saved content from https://docs.ros.org/en/iron/p/ament_cmake_libraries/ to MongoDB with id 67427fd1b98d7a37c0433843\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[50], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Start DFS scraping from the base URL\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mscrape_page_dfs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbase_url\u001b[49m\u001b[43m)\u001b[49m\n", + "Cell \u001b[0;32mIn[49], line 39\u001b[0m, in \u001b[0;36mscrape_page_dfs\u001b[0;34m(url, depth, max_depth)\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[38;5;66;03m# Ensure the link is within the docs.ros.org domain and not visited\u001b[39;00m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m base_url \u001b[38;5;129;01min\u001b[39;00m full_url \u001b[38;5;129;01mand\u001b[39;00m full_url \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m visited_urls:\n\u001b[0;32m---> 39\u001b[0m \u001b[43mscrape_page_dfs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfull_url\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdepth\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmax_depth\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mError scraping \u001b[39m\u001b[38;5;132;01m{\u001b[39;00murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "Cell \u001b[0;32mIn[49], line 39\u001b[0m, in \u001b[0;36mscrape_page_dfs\u001b[0;34m(url, depth, max_depth)\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[38;5;66;03m# Ensure the link is within the docs.ros.org domain and not visited\u001b[39;00m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m base_url \u001b[38;5;129;01min\u001b[39;00m full_url \u001b[38;5;129;01mand\u001b[39;00m full_url \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m visited_urls:\n\u001b[0;32m---> 39\u001b[0m \u001b[43mscrape_page_dfs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfull_url\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdepth\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmax_depth\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mError scraping \u001b[39m\u001b[38;5;132;01m{\u001b[39;00murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + " \u001b[0;31m[... skipping similar frames: scrape_page_dfs at line 39 (2 times)]\u001b[0m\n", + "Cell \u001b[0;32mIn[49], line 39\u001b[0m, in \u001b[0;36mscrape_page_dfs\u001b[0;34m(url, depth, max_depth)\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[38;5;66;03m# Ensure the link is within the docs.ros.org domain and not visited\u001b[39;00m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m base_url \u001b[38;5;129;01min\u001b[39;00m full_url \u001b[38;5;129;01mand\u001b[39;00m full_url \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m visited_urls:\n\u001b[0;32m---> 39\u001b[0m \u001b[43mscrape_page_dfs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfull_url\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdepth\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmax_depth\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mError scraping \u001b[39m\u001b[38;5;132;01m{\u001b[39;00murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00me\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "Cell \u001b[0;32mIn[49], line 13\u001b[0m, in \u001b[0;36mscrape_page_dfs\u001b[0;34m(url, depth, max_depth)\u001b[0m\n\u001b[1;32m 9\u001b[0m visited_urls\u001b[38;5;241m.\u001b[39madd(url)\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 12\u001b[0m \u001b[38;5;66;03m# Fetch the page content\u001b[39;00m\n\u001b[0;32m---> 13\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[43mrequests\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m10\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m response\u001b[38;5;241m.\u001b[39mstatus_code \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m200\u001b[39m:\n\u001b[1;32m 15\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFailed to access \u001b[39m\u001b[38;5;132;01m{\u001b[39;00murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m (Status code: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse\u001b[38;5;241m.\u001b[39mstatus_code\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/requests/api.py:73\u001b[0m, in \u001b[0;36mget\u001b[0;34m(url, params, **kwargs)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget\u001b[39m(url, params\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 63\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124mr\u001b[39m\u001b[38;5;124;03m\"\"\"Sends a GET request.\u001b[39;00m\n\u001b[1;32m 64\u001b[0m \n\u001b[1;32m 65\u001b[0m \u001b[38;5;124;03m :param url: URL for the new :class:`Request` object.\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[38;5;124;03m :rtype: requests.Response\u001b[39;00m\n\u001b[1;32m 71\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 73\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mget\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/requests/api.py:59\u001b[0m, in \u001b[0;36mrequest\u001b[0;34m(method, url, **kwargs)\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[38;5;66;03m# By using the 'with' statement we are sure the session is closed, thus we\u001b[39;00m\n\u001b[1;32m 56\u001b[0m \u001b[38;5;66;03m# avoid leaving sockets open which can trigger a ResourceWarning in some\u001b[39;00m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;66;03m# cases, and look like a memory leak in others.\u001b[39;00m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m sessions\u001b[38;5;241m.\u001b[39mSession() \u001b[38;5;28;01mas\u001b[39;00m session:\n\u001b[0;32m---> 59\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43msession\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/requests/sessions.py:589\u001b[0m, in \u001b[0;36mSession.request\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 584\u001b[0m send_kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 585\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtimeout\u001b[39m\u001b[38;5;124m\"\u001b[39m: timeout,\n\u001b[1;32m 586\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mallow_redirects\u001b[39m\u001b[38;5;124m\"\u001b[39m: allow_redirects,\n\u001b[1;32m 587\u001b[0m }\n\u001b[1;32m 588\u001b[0m send_kwargs\u001b[38;5;241m.\u001b[39mupdate(settings)\n\u001b[0;32m--> 589\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43msend_kwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 591\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m resp\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/requests/sessions.py:703\u001b[0m, in \u001b[0;36mSession.send\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 700\u001b[0m start \u001b[38;5;241m=\u001b[39m preferred_clock()\n\u001b[1;32m 702\u001b[0m \u001b[38;5;66;03m# Send the request\u001b[39;00m\n\u001b[0;32m--> 703\u001b[0m r \u001b[38;5;241m=\u001b[39m \u001b[43madapter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[38;5;66;03m# Total elapsed time of the request (approximately)\u001b[39;00m\n\u001b[1;32m 706\u001b[0m elapsed \u001b[38;5;241m=\u001b[39m preferred_clock() \u001b[38;5;241m-\u001b[39m start\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/requests/adapters.py:667\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 664\u001b[0m timeout \u001b[38;5;241m=\u001b[39m TimeoutSauce(connect\u001b[38;5;241m=\u001b[39mtimeout, read\u001b[38;5;241m=\u001b[39mtimeout)\n\u001b[1;32m 666\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 667\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43murlopen\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 668\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 669\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 670\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 671\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 672\u001b[0m \u001b[43m \u001b[49m\u001b[43mredirect\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 673\u001b[0m \u001b[43m \u001b[49m\u001b[43massert_same_host\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 674\u001b[0m \u001b[43m \u001b[49m\u001b[43mpreload_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 675\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecode_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 676\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmax_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 677\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 678\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunked\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 679\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 681\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ProtocolError, \u001b[38;5;167;01mOSError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 682\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mConnectionError\u001b[39;00m(err, request\u001b[38;5;241m=\u001b[39mrequest)\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/urllib3/connectionpool.py:789\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)\u001b[0m\n\u001b[1;32m 786\u001b[0m response_conn \u001b[38;5;241m=\u001b[39m conn \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m release_conn \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 788\u001b[0m \u001b[38;5;66;03m# Make the request on the HTTPConnection object\u001b[39;00m\n\u001b[0;32m--> 789\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_make_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 790\u001b[0m \u001b[43m \u001b[49m\u001b[43mconn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 791\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 792\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 793\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout_obj\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 794\u001b[0m \u001b[43m \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbody\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 795\u001b[0m \u001b[43m \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 796\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunked\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunked\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 797\u001b[0m \u001b[43m \u001b[49m\u001b[43mretries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mretries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 798\u001b[0m \u001b[43m \u001b[49m\u001b[43mresponse_conn\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresponse_conn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 799\u001b[0m \u001b[43m \u001b[49m\u001b[43mpreload_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpreload_content\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 800\u001b[0m \u001b[43m \u001b[49m\u001b[43mdecode_content\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdecode_content\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 801\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mresponse_kw\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 802\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 804\u001b[0m \u001b[38;5;66;03m# Everything went great!\u001b[39;00m\n\u001b[1;32m 805\u001b[0m clean_exit \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/urllib3/connectionpool.py:536\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[0;34m(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)\u001b[0m\n\u001b[1;32m 534\u001b[0m \u001b[38;5;66;03m# Receive the response from the server\u001b[39;00m\n\u001b[1;32m 535\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 536\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetresponse\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 537\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (BaseSSLError, \u001b[38;5;167;01mOSError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 538\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_timeout(err\u001b[38;5;241m=\u001b[39me, url\u001b[38;5;241m=\u001b[39murl, timeout_value\u001b[38;5;241m=\u001b[39mread_timeout)\n", + "File \u001b[0;32m~/Documents/Develop/ros2-rag-project/myenv/lib/python3.9/site-packages/urllib3/connection.py:507\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 504\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mresponse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m HTTPResponse\n\u001b[1;32m 506\u001b[0m \u001b[38;5;66;03m# Get the response from http.client.HTTPConnection\u001b[39;00m\n\u001b[0;32m--> 507\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetresponse\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 509\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 510\u001b[0m assert_header_parsing(httplib_response\u001b[38;5;241m.\u001b[39mmsg)\n", + "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.20/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:1377\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1375\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1376\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1377\u001b[0m \u001b[43mresponse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbegin\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1378\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mConnectionError\u001b[39;00m:\n\u001b[1;32m 1379\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose()\n", + "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.20/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:320\u001b[0m, in \u001b[0;36mHTTPResponse.begin\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;66;03m# read until we get a non-100 response\u001b[39;00m\n\u001b[1;32m 319\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 320\u001b[0m version, status, reason \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_read_status\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 321\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m status \u001b[38;5;241m!=\u001b[39m CONTINUE:\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", + "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.20/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py:281\u001b[0m, in \u001b[0;36mHTTPResponse._read_status\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_read_status\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m--> 281\u001b[0m line \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreadline\u001b[49m\u001b[43m(\u001b[49m\u001b[43m_MAXLINE\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124miso-8859-1\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(line) \u001b[38;5;241m>\u001b[39m _MAXLINE:\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m LineTooLong(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstatus line\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.20/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socket.py:716\u001b[0m, in \u001b[0;36mSocketIO.readinto\u001b[0;34m(self, b)\u001b[0m\n\u001b[1;32m 714\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 715\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 716\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv_into\u001b[49m\u001b[43m(\u001b[49m\u001b[43mb\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 717\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m timeout:\n\u001b[1;32m 718\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_timeout_occurred \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.20/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py:1275\u001b[0m, in \u001b[0;36mSSLSocket.recv_into\u001b[0;34m(self, buffer, nbytes, flags)\u001b[0m\n\u001b[1;32m 1271\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m flags \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 1272\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 1273\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnon-zero flags not allowed in calls to recv_into() on \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 1274\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m)\n\u001b[0;32m-> 1275\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnbytes\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1276\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1277\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mrecv_into(buffer, nbytes, flags)\n", + "File \u001b[0;32m/opt/homebrew/Cellar/python@3.9/3.9.20/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py:1133\u001b[0m, in \u001b[0;36mSSLSocket.read\u001b[0;34m(self, len, buffer)\u001b[0m\n\u001b[1;32m 1131\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 1132\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m buffer \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m-> 1133\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sslobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1134\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1135\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sslobj\u001b[38;5;241m.\u001b[39mread(\u001b[38;5;28mlen\u001b[39m)\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "# Start DFS scraping from the base URL\n", + "scrape_page_dfs(base_url)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Crawling completed. MongoDB connection closed.\n" + ] + } + ], + "source": [ + "# Close the MongoDB connection\n", + "client.close()\n", + "print(\"Crawling completed. MongoDB connection closed.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Documents in 'ros_distributions' collection:\n", + "Number of urls ingested: 2657\n" + ] + } + ], + "source": [ + "collections = db['ros_distributions']\n", + "documents = collections.find()\n", + "print(f\"Documents in '{collections.name}' collection:\")\n", + "i=0\n", + "for document in documents:\n", + " i+=1\n", + "print(\"Number of urls ingested:\", i)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/04_llama_rag.ipynb b/notebooks/04_llama_rag.ipynb index 04399c5..4b320cf 100644 --- a/notebooks/04_llama_rag.ipynb +++ b/notebooks/04_llama_rag.ipynb @@ -422,9 +422,9 @@ ], "metadata": { "kernelspec": { - "display_name": "lm", + "display_name": "myenv", "language": "python", - "name": "lm" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -436,7 +436,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.9.20" } }, "nbformat": 4, diff --git a/notebooks/service_connectivity_test.ipynb b/notebooks/service_connectivity_test.ipynb new file mode 100644 index 0000000..a1d7462 --- /dev/null +++ b/notebooks/service_connectivity_test.ipynb @@ -0,0 +1,245 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pymongo\n", + "from qdrant_client import QdrantClient\n", + "import requests\n", + "from clearml import Task\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "❌ MongoDB Connection Failed: mongodb:27017: [Errno 8] nodename nor servname provided, or not known (configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms), Timeout: 30s, Topology Description: ]>\n" + ] + }, + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def test_mongodb():\n", + " try:\n", + " client = pymongo.MongoClient(\"mongodb://mongodb:27017/\")\n", + " db_list = client.list_database_names()\n", + " print(\"✅ MongoDB Connection Successful\")\n", + " print(f\"Available databases: {db_list}\")\n", + " return True\n", + " except Exception as e:\n", + " print(f\"❌ MongoDB Connection Failed: {str(e)}\")\n", + " return False\n", + "test_mongodb()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "❌ Qdrant Connection Failed: [Errno 8] nodename nor servname provided, or not known\n" + ] + }, + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def test_qdrant():\n", + " try:\n", + " client = QdrantClient(host=\"qdrant\", port=6333)\n", + " service_info = client.get_collections()\n", + " print(\"✅ Qdrant Connection Successful\")\n", + " print(f\"Collections info: {service_info}\")\n", + " return True\n", + " except Exception as e:\n", + " print(f\"❌ Qdrant Connection Failed: {str(e)}\")\n", + " return False\n", + "test_qdrant()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "❌ API Server Connection Failed: HTTPConnectionPool(host='apiserver', port=8008): Max retries exceeded with url: /health (Caused by NameResolutionError(\": Failed to resolve 'apiserver' ([Errno 8] nodename nor servname provided, or not known)\"))\n", + "❌ Web Server Connection Failed: HTTPConnectionPool(host='webserver', port=8080): Max retries exceeded with url: /health (Caused by NameResolutionError(\": Failed to resolve 'webserver' ([Errno 8] nodename nor servname provided, or not known)\"))\n", + "❌ File Server Connection Failed: HTTPConnectionPool(host='fileserver', port=8081): Max retries exceeded with url: /health (Caused by NameResolutionError(\": Failed to resolve 'fileserver' ([Errno 8] nodename nor servname provided, or not known)\"))\n" + ] + }, + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def test_clearml_services():\n", + " services = {\n", + " 'API Server': 'http://apiserver:8008',\n", + " 'Web Server': 'http://webserver:8080',\n", + " 'File Server': 'http://fileserver:8081'\n", + " }\n", + " results = {}\n", + " for service_name, url in services.items():\n", + " try:\n", + " response = requests.get(f\"{url}/health\")\n", + " if response.status_code == 200:\n", + " print(f\"✅ {service_name} Connection Successful\")\n", + " results[service_name] = True\n", + " else:\n", + " print(f\"❌ {service_name} Response Code: {response.status_code}\")\n", + " results[service_name] = False\n", + " except Exception as e:\n", + " print(f\"❌ {service_name} Connection Failed: {str(e)}\")\n", + " results[service_name] = False\n", + "\n", + " return all(results.values())\n", + "test_clearml_services()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'app'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[5], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mapp\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmongodb\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m MongoDBClient\n\u001b[1;32m 3\u001b[0m mongo_client \u001b[38;5;241m=\u001b[39m MongoDBClient()\n\u001b[1;32m 4\u001b[0m documents \u001b[38;5;241m=\u001b[39m mongo_client\u001b[38;5;241m.\u001b[39mdocs_collection\u001b[38;5;241m.\u001b[39mfind({}, {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msource.url\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;241m1\u001b[39m})\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'app'" + ] + } + ], + "source": [ + "from app.utils.mongodb import MongoDBClient\n", + "\n", + "mongo_client = MongoDBClient()\n", + "documents = mongo_client.docs_collection.find({}, {\"source.url\": 1})\n", + "urls = [doc['source']['url'] for doc in documents]\n", + "print(\"Ingested URLs:\")\n", + "for url in urls:\n", + " print(url)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ GitHub API Connection Successful\n", + "❌ YouTube API Connection Failed: playlistId parameter cannot be found.\". Details: \"[{'message': \"The playlist identified with the request's playlistId parameter cannot be found.\", 'domain': 'youtube.playlistItem', 'reason': 'playlistNotFound', 'location': 'playlistId', 'locationType': 'parameter'}]\">\n" + ] + } + ], + "source": [ + "def test_api_keys():\n", + " import yaml\n", + " from github import Github\n", + " from googleapiclient.discovery import build\n", + " \n", + " # Load API keys\n", + " with open('../app/configs/api_keys.yaml', 'r') as f:\n", + " api_keys = yaml.safe_load(f)\n", + " \n", + " # Test GitHub\n", + " try:\n", + " g = Github(api_keys['github']['access_token'])\n", + " user = g.get_user()\n", + " print(f\"✅ GitHub API Connection Successful\")\n", + " except Exception as e:\n", + " print(f\"❌ GitHub API Connection Failed: {str(e)}\")\n", + " \n", + " # Test YouTube\n", + " try:\n", + " youtube = build('youtube', 'v3', developerKey=api_keys['youtube']['api_key'])\n", + " request = youtube.playlistItems().list(\n", + " part='snippet',\n", + " playlistId='PLNw1_R4SfJQf_i5un9AGGj1jmqWJ4yE4i',\n", + " maxResults=1\n", + " )\n", + " response = request.execute()\n", + " print(f\"✅ YouTube API Connection Successful\")\n", + " except Exception as e:\n", + " print(f\"❌ YouTube API Connection Failed: {str(e)}\")\n", + "\n", + "test_api_keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/sources.yaml b/notebooks/sources.yaml deleted file mode 100644 index bc7721b..0000000 --- a/notebooks/sources.yaml +++ /dev/null @@ -1,66 +0,0 @@ -documentation_sources: - core_docs: - - name: "ROS2 Humble Documentation" - url: "https://docs.ros.org/en/humble/" - version: "humble" - sections: - - "Tutorials" - - "How-To Guides" - - "Concepts" - - "API Reference" - - - name: "Navigation2 Documentation" - url: "https://docs.nav2.org/" - version: "latest" - sections: - - "Getting Started" - - "Tutorials" - - "Configuration" - - "API Reference" - - - name: "MoveIt2 Documentation" - url: "https://moveit.ros.org/" - version: "latest" - - - name: "Gazebo Documentation" - url: "https://gazebosim.org/docs" - version: "latest" - -youtube_channels: - - name: "ROS Foundation" - channel_id: "UCXEEpqD_iN0_J6fTvXGRakg" - playlists: - - name: "ROS2 Tutorials" - id: "PLK0b4e05LnzYNBzPyyMCAW1U8WP2FNCPu" - - - name: "The Construct" - channel_url: "https://www.youtube.com/@TheConstruct" - focus: ["ROS2", "Navigation", "Simulation"] - - - name: "Articulated Robotics" - channel_url: "https://www.youtube.com/@ArticulatedRobotics" - focus: ["ROS2", "Navigation"] - -github_repositories: - core: - - name: "ROS2 Main" - url: "https://github.com/ros2/ros2" - branch: "humble" - - - name: "ROS2 Examples" - url: "https://github.com/ros2/examples" - branch: "humble" - - navigation: - - name: "Navigation2" - url: "https://github.com/ros-planning/navigation2" - branch: "main" - - - name: "Geometry2" - url: "https://github.com/ros2/geometry2" - branch: "ros2" - - motion_planning: - - name: "MoveIt2" - url: "https://github.com/ros-planning/moveit2" - branch: "main" \ No newline at end of file diff --git a/notebooks/test.ipynb b/notebooks/test.ipynb new file mode 100644 index 0000000..8e0c609 --- /dev/null +++ b/notebooks/test.ipynb @@ -0,0 +1,849 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from youtube_transcript_api import YouTubeTranscriptApi\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "video_id = '0aPbWsyENA8'\n", + "json = YouTubeTranscriptApi.get_transcript(video_id, languages=['en'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'text': 'hey everyone welcome to this tutorial',\n", + " 'start': 0.16,\n", + " 'duration': 5.199},\n", + " {'text': 'series crash course on ros2 if you have',\n", + " 'start': 2.159,\n", + " 'duration': 5.921},\n", + " {'text': 'never used robot operating system before',\n", + " 'start': 5.359,\n", + " 'duration': 5.121},\n", + " {'text': 'even roswell or if you want a practical',\n", + " 'start': 8.08,\n", + " 'duration': 4.88},\n", + " {'text': 'and quick refresher of the basics this',\n", + " 'start': 10.48,\n", + " 'duration': 4.88},\n", + " {'text': 'series is for you and very quickly so',\n", + " 'start': 12.96,\n", + " 'duration': 5.2},\n", + " {'text': \"you don't get confused ross means robot\",\n", + " 'start': 15.36,\n", + " 'duration': 5.6},\n", + " {'text': 'operating system ros1 is the first',\n", + " 'start': 18.16,\n", + " 'duration': 6.24},\n", + " {'text': 'version of ros and ros2 is the second',\n", + " 'start': 20.96,\n", + " 'duration': 6.239},\n", + " {'text': 'version of ross ross 2 is now stable',\n", + " 'start': 24.4,\n", + " 'duration': 4.48},\n", + " {'text': 'enough to be used so this is the',\n", + " 'start': 27.199,\n", + " 'duration': 4.16},\n", + " {'text': 'recommended way to start with ross in',\n", + " 'start': 28.88,\n", + " 'duration': 4.32},\n", + " {'text': 'this series i will sometimes use the',\n", + " 'start': 31.359,\n", + " 'duration': 4.401},\n", + " {'text': 'term ross or ros 2 and when i do i will',\n", + " 'start': 33.2,\n", + " 'duration': 4.96},\n", + " {'text': 'be talking about the same thing',\n", + " 'start': 35.76,\n", + " 'duration': 4.319},\n", + " {'text': 'so the goal of this crash course is',\n", + " 'start': 38.16,\n", + " 'duration': 4.399},\n", + " {'text': 'simply to get you started with roster in',\n", + " 'start': 40.079,\n", + " 'duration': 4.96},\n", + " {'text': 'a very short amount of time you will',\n", + " 'start': 42.559,\n", + " 'duration': 4.241},\n", + " {'text': 'learn how to install and set up',\n", + " 'start': 45.039,\n", + " 'duration': 4.081},\n", + " {'text': 'everything how to use the main roster',\n", + " 'start': 46.8,\n", + " 'duration': 4.56},\n", + " {'text': 'concepts with the command line interface',\n", + " 'start': 49.12,\n", + " 'duration': 4.48},\n", + " {'text': 'and tools and you will also write your',\n", + " 'start': 51.36,\n", + " 'duration': 5.359},\n", + " {'text': 'own roster programs with python in fact',\n", + " 'start': 53.6,\n", + " 'duration': 4.639},\n", + " {'text': 'throughout the series we will do',\n", + " 'start': 56.719,\n", + " 'duration': 3.68},\n", + " {'text': 'together a small but complete roster',\n", + " 'start': 58.239,\n", + " 'duration': 5.201},\n", + " {'text': 'application using a 2d simulation of a',\n", + " 'start': 60.399,\n", + " 'duration': 5.441},\n", + " {'text': 'robot i have designed the series so that',\n", + " 'start': 63.44,\n", + " 'duration': 3.92},\n", + " {'text': 'you can really get a better', 'start': 65.84, 'duration': 3.84},\n", + " {'text': 'understanding of the global picture and',\n", + " 'start': 67.36,\n", + " 'duration': 4.56},\n", + " {'text': 'also get some practical knowledge that',\n", + " 'start': 69.68,\n", + " 'duration': 4.72},\n", + " {'text': 'will be useful for your next steps with',\n", + " 'start': 71.92,\n", + " 'duration': 4.72},\n", + " {'text': 'ros 2. in this tutorial series i will',\n", + " 'start': 74.4,\n", + " 'duration': 5.12},\n", + " {'text': 'target the rost2 humble distribution but',\n", + " 'start': 76.64,\n", + " 'duration': 5.119},\n", + " {'text': 'the concepts and most of the code will',\n", + " 'start': 79.52,\n", + " 'duration': 5.52},\n", + " {'text': 'also work for other roster distributions',\n", + " 'start': 81.759,\n", + " 'duration': 5.441},\n", + " {'text': 'now there are some prerequisites you',\n", + " 'start': 85.04,\n", + " 'duration': 4.8},\n", + " {'text': 'need in order to use ros basically you',\n", + " 'start': 87.2,\n", + " 'duration': 5.2},\n", + " {'text': 'have to be familiar with ubuntu and the',\n", + " 'start': 89.84,\n", + " 'duration': 5.12},\n", + " {'text': 'linux command line and to write a ros',\n", + " 'start': 92.4,\n", + " 'duration': 5.2},\n", + " {'text': 'code you will also need to know a bit of',\n", + " 'start': 94.96,\n", + " 'duration': 4.08},\n", + " {'text': 'python and c', 'start': 97.6, 'duration': 3.6},\n", + " {'text': 'but here we will stick to python so just',\n", + " 'start': 99.04,\n", + " 'duration': 3.759},\n", + " {'text': 'python will be fine', 'start': 101.2, 'duration': 3.36},\n", + " {'text': 'now this crash course is great to get',\n", + " 'start': 102.799,\n", + " 'duration': 3.521},\n", + " {'text': 'you started and if you want to go',\n", + " 'start': 104.56,\n", + " 'duration': 3.839},\n", + " {'text': 'further and dive into more details',\n", + " 'start': 106.32,\n", + " 'duration': 5.2},\n", + " {'text': 'concepts projects and c plus plus code i',\n", + " 'start': 108.399,\n", + " 'duration': 5.36},\n", + " {'text': 'have also a much bigger and complete',\n", + " 'start': 111.52,\n", + " 'duration': 4.4},\n", + " {'text': 'course on ros 2. so if you are',\n", + " 'start': 113.759,\n", + " 'duration': 4.241},\n", + " {'text': \"interested i've put a link in the video\",\n", + " 'start': 115.92,\n", + " 'duration': 4.08},\n", + " {'text': 'description below and i will talk a bit',\n", + " 'start': 118.0,\n", + " 'duration': 4.64},\n", + " {'text': \"more about this later on now let's get\",\n", + " 'start': 120.0,\n", + " 'duration': 4.64},\n", + " {'text': 'started with the series in this first',\n", + " 'start': 122.64,\n", + " 'duration': 4.0},\n", + " {'text': 'episode we are going to install and set',\n", + " 'start': 124.64,\n", + " 'duration': 4.839},\n", + " {'text': 'up ross to humble on ubuntu', 'start': 126.64, 'duration': 5.84},\n", + " {'text': '22.04 so that in the next episode you',\n", + " 'start': 129.479,\n", + " 'duration': 5.721},\n", + " {'text': 'can start using ros functionalities here',\n", + " 'start': 132.48,\n", + " 'duration': 5.68},\n", + " {'text': 'i am going to start from ubuntu 22.04',\n", + " 'start': 135.2,\n", + " 'duration': 5.039},\n", + " {'text': 'that i have already installed on a',\n", + " 'start': 138.16,\n", + " 'duration': 5.12},\n", + " {'text': 'virtual machine in virtualbox you can',\n", + " 'start': 140.239,\n", + " 'duration': 5.521},\n", + " {'text': 'use either ubuntu installed with a dual',\n", + " 'start': 143.28,\n", + " 'duration': 5.039},\n", + " {'text': 'boot on your computer or in a virtual',\n", + " 'start': 145.76,\n", + " 'duration': 4.88},\n", + " {'text': \"machine it's up to you so to install\",\n", + " 'start': 148.319,\n", + " 'duration': 5.121},\n", + " {'text': \"rost2 let's first open a terminal and\",\n", + " 'start': 150.64,\n", + " 'duration': 4.72},\n", + " {'text': \"i'm going to put this on the side and\",\n", + " 'start': 153.44,\n", + " 'duration': 4.48},\n", + " {'text': \"let's also open a web browser i'm going\",\n", + " 'start': 155.36,\n", + " 'duration': 5.84},\n", + " {'text': 'to open firefox here', 'start': 157.92, 'duration': 6.16},\n", + " {'text': \"okay and let's also put this on this\",\n", + " 'start': 161.2,\n", + " 'duration': 5.759},\n", + " {'text': \"side and let's search for ros to\",\n", + " 'start': 164.08,\n", + " 'duration': 5.12},\n", + " {'text': 'humble', 'start': 166.959, 'duration': 4.56},\n", + " {'text': \"okay you will get to so let's zoom a bit\",\n", + " 'start': 169.2,\n", + " 'duration': 3.44},\n", + " {'text': 'here', 'start': 171.519, 'duration': 3.281},\n", + " {'text': 'you will get to this page on', 'start': 172.64, 'duration': 4.8},\n", + " {'text': 'docs.ros.org', 'start': 174.8, 'duration': 4.799},\n", + " {'text': 'okay make sure you have a humble in the',\n", + " 'start': 177.44,\n", + " 'duration': 3.84},\n", + " {'text': \"url if you don't have\", 'start': 179.599, 'duration': 3.36},\n", + " {'text': 'maybe you are reading the documentation',\n", + " 'start': 181.28,\n", + " 'duration': 3.599},\n", + " {'text': \"for another version so let's click on\",\n", + " 'start': 182.959,\n", + " 'duration': 4.56},\n", + " {'text': 'humble here', 'start': 184.879, 'duration': 2.64},\n", + " {'text': 'and then', 'start': 188.159, 'duration': 2.641},\n", + " {'text': 'here you can see the table of contents',\n", + " 'start': 189.2,\n", + " 'duration': 4.88},\n", + " {'text': \"and you're gonna choose installation\",\n", + " 'start': 190.8,\n", + " 'duration': 5.68},\n", + " {'text': 'and click on install humble', 'start': 194.08, 'duration': 3.84},\n", + " {'text': \"all right now you're gonna choose the\",\n", + " 'start': 196.48,\n", + " 'duration': 3.44},\n", + " {'text': 'binary packages installation not',\n", + " 'start': 197.92,\n", + " 'duration': 4.08},\n", + " {'text': \"building from source and you're gonna go\",\n", + " 'start': 199.92,\n", + " 'duration': 6.48},\n", + " {'text': 'here with ubuntu and debian packages',\n", + " 'start': 202.0,\n", + " 'duration': 6.159},\n", + " {'text': 'and now we have the instructions to',\n", + " 'start': 206.4,\n", + " 'duration': 5.119},\n", + " {'text': \"install ros2 on ubuntu so i'm going to\",\n", + " 'start': 208.159,\n", + " 'duration': 5.041},\n", + " {'text': 'follow here just the instructions that',\n", + " 'start': 211.519,\n", + " 'duration': 4.08},\n", + " {'text': 'we need and just a quick note is that',\n", + " 'start': 213.2,\n", + " 'duration': 4.319},\n", + " {'text': 'maybe when you browse this documentation',\n", + " 'start': 215.599,\n", + " 'duration': 4.321},\n", + " {'text': 'the instructions will have changed a',\n", + " 'start': 217.519,\n", + " 'duration': 4.161},\n", + " {'text': \"tiny bit but that's okay it's just\",\n", + " 'start': 219.92,\n", + " 'duration': 4.0},\n", + " {'text': 'because well the documentation is quite',\n", + " 'start': 221.68,\n", + " 'duration': 4.32},\n", + " {'text': 'frequently updated so if you see',\n", + " 'start': 223.92,\n", + " 'duration': 3.52},\n", + " {'text': 'something that is just a little bit',\n", + " 'start': 226.0,\n", + " 'duration': 3.44},\n", + " {'text': 'different no worries just follow the',\n", + " 'start': 227.44,\n", + " 'duration': 3.92},\n", + " {'text': 'instructions and everything will be okay',\n", + " 'start': 229.44,\n", + " 'duration': 3.68},\n", + " {'text': 'so the first thing is we need to make',\n", + " 'start': 231.36,\n", + " 'duration': 4.32},\n", + " {'text': \"sure that we have utf-8 so we're going\",\n", + " 'start': 233.12,\n", + " 'duration': 3.28},\n", + " {'text': 'to', 'start': 235.68, 'duration': 2.4},\n", + " {'text': 'type local in', 'start': 236.4, 'duration': 4.0},\n", + " {'text': 'the terminal here and make sure that we',\n", + " 'start': 238.08,\n", + " 'duration': 4.879},\n", + " {'text': \"have utf-8 so here it's good\", 'start': 240.4, 'duration': 4.96},\n", + " {'text': \"if you don't have it then you're gonna\",\n", + " 'start': 242.959,\n", + " 'duration': 4.721},\n", + " {'text': 'well just run those commands', 'start': 245.36, 'duration': 4.48},\n", + " {'text': \"but your passwords okay so that's gonna\",\n", + " 'start': 247.68,\n", + " 'duration': 4.24},\n", + " {'text': 'install some stuff', 'start': 249.84, 'duration': 5.039},\n", + " {'text': \"it's already installed for me\", 'start': 251.92, 'duration': 5.599},\n", + " {'text': 'you run those lines here', 'start': 254.879, 'duration': 4.401},\n", + " {'text': \"actually let's\", 'start': 257.519, 'duration': 3.921},\n", + " {'text': 'put this', 'start': 259.28, 'duration': 4.24},\n", + " {'text': 'like that', 'start': 261.44, 'duration': 6.6},\n", + " {'text': 'all right so you run the four lines',\n", + " 'start': 263.52,\n", + " 'duration': 4.52},\n", + " {'text': \"and then let's check local again and of\",\n", + " 'start': 269.12,\n", + " 'duration': 6.079},\n", + " {'text': \"course it's okay you have utf-8\",\n", + " 'start': 271.6,\n", + " 'duration': 6.319},\n", + " {'text': 'now you will need to set up the sources',\n", + " 'start': 275.199,\n", + " 'duration': 4.56},\n", + " {'text': \"because you can't just install ros2 like\",\n", + " 'start': 277.919,\n", + " 'duration': 3.681},\n", + " {'text': 'that you will need to set up the sources',\n", + " 'start': 279.759,\n", + " 'duration': 4.241},\n", + " {'text': 'so that your computer here can find',\n", + " 'start': 281.6,\n", + " 'duration': 5.12},\n", + " {'text': 'where to download roster and well those',\n", + " 'start': 284.0,\n", + " 'duration': 5.28},\n", + " {'text': 'instructions here may be removed in the',\n", + " 'start': 286.72,\n", + " 'duration': 5.199},\n", + " {'text': \"future or maybe modified so if you don't\",\n", + " 'start': 289.28,\n", + " 'duration': 4.4},\n", + " {'text': \"see that don't worry just go to the next\",\n", + " 'start': 291.919,\n", + " 'duration': 4.56},\n", + " {'text': 'step but what you can do is just do this',\n", + " 'start': 293.68,\n", + " 'duration': 5.76},\n", + " {'text': 'apt cache policy grip universe and if',\n", + " 'start': 296.479,\n", + " 'duration': 6.081},\n", + " {'text': 'you see stuff like that with 500',\n", + " 'start': 299.44,\n", + " 'duration': 5.12},\n", + " {'text': 'and then well you see', 'start': 302.56, 'duration': 4.56},\n", + " {'text': 'jammy and universe stuff', 'start': 304.56, 'duration': 4.24},\n", + " {'text': \"then that's okay you don't necessarily\",\n", + " 'start': 307.12,\n", + " 'duration': 3.12},\n", + " {'text': 'have to have the exact same thing with',\n", + " 'start': 308.8,\n", + " 'duration': 4.32},\n", + " {'text': 'for example us here you can see i have',\n", + " 'start': 310.24,\n", + " 'duration': 4.799},\n", + " {'text': 'fr but', 'start': 313.12, 'duration': 4.0},\n", + " {'text': 'the important thing is that you see 500',\n", + " 'start': 315.039,\n", + " 'duration': 4.801},\n", + " {'text': \"and universe so if you don't have those\",\n", + " 'start': 317.12,\n", + " 'duration': 4.48},\n", + " {'text': \"you can run those two commands here i'm\",\n", + " 'start': 319.84,\n", + " 'duration': 3.68},\n", + " {'text': 'not gonna run those but you can run',\n", + " 'start': 321.6,\n", + " 'duration': 4.4},\n", + " {'text': \"there if you don't have the correct\",\n", + " 'start': 323.52,\n", + " 'duration': 4.48},\n", + " {'text': \"lines and now it's really the step to\",\n", + " 'start': 326.0,\n", + " 'duration': 4.08},\n", + " {'text': \"actually set up the sources so you're\",\n", + " 'start': 328.0,\n", + " 'duration': 4.56},\n", + " {'text': 'gonna run this line first', 'start': 330.08, 'duration': 4.399},\n", + " {'text': 'to install curl and different', 'start': 332.56, 'duration': 3.919},\n", + " {'text': 'functionalities', 'start': 334.479, 'duration': 3.681},\n", + " {'text': 'so here actually i already installed it',\n", + " 'start': 336.479,\n", + " 'duration': 3.841},\n", + " {'text': 'before so nothing to do for me then you',\n", + " 'start': 338.16,\n", + " 'duration': 4.96},\n", + " {'text': 'run this line', 'start': 340.32, 'duration': 5.2},\n", + " {'text': 'okay and add the repository to the',\n", + " 'start': 343.12,\n", + " 'duration': 4.16},\n", + " {'text': 'sources so you just', 'start': 345.52, 'duration': 5.119},\n", + " {'text': 'copy and paste the line and then you are',\n", + " 'start': 347.28,\n", + " 'duration': 6.08},\n", + " {'text': 'good what you can do is now do an update',\n", + " 'start': 350.639,\n", + " 'duration': 4.881},\n", + " {'text': 'so pseudo apt update', 'start': 353.36, 'duration': 4.48},\n", + " {'text': 'this is going to update', 'start': 355.52, 'duration': 3.76},\n", + " {'text': 'and you can see that you should have',\n", + " 'start': 357.84,\n", + " 'duration': 3.24},\n", + " {'text': 'something like that', 'start': 359.28, 'duration': 4.639},\n", + " {'text': 'packages.ross.org with ros2 so you will',\n", + " 'start': 361.08,\n", + " 'duration': 5.8},\n", + " {'text': 'have something similar and one important',\n", + " 'start': 363.919,\n", + " 'duration': 5.601},\n", + " {'text': 'thing is that before you install rost2',\n", + " 'start': 366.88,\n", + " 'duration': 5.92},\n", + " {'text': \"let's do sudo apt upgrade to upgrade all\",\n", + " 'start': 369.52,\n", + " 'duration': 4.959},\n", + " {'text': 'the packages we have', 'start': 372.8, 'duration': 3.36},\n", + " {'text': 'okay so you may have a lot', 'start': 374.479, 'duration': 3.84},\n", + " {'text': 'or not it depends when was the last time',\n", + " 'start': 376.16,\n", + " 'duration': 4.319},\n", + " {'text': 'you actually upgraded your system',\n", + " 'start': 378.319,\n", + " 'duration': 3.841},\n", + " {'text': \"so i'm just going to put yes and wait\",\n", + " 'start': 380.479,\n", + " 'duration': 4.401},\n", + " {'text': 'for the upgrade', 'start': 382.16, 'duration': 2.72},\n", + " {'text': 'okay and now you can go down into the',\n", + " 'start': 386.24,\n", + " 'duration': 5.12},\n", + " {'text': 'instructions so you have a warning here',\n", + " 'start': 389.6,\n", + " 'duration': 3.599},\n", + " {'text': 'but nothing to worry about if you have',\n", + " 'start': 391.36,\n", + " 'duration': 4.559},\n", + " {'text': 'correctly updated and upgraded the',\n", + " 'start': 393.199,\n", + " 'duration': 5.601},\n", + " {'text': 'packages so now everything is up to date',\n", + " 'start': 395.919,\n", + " 'duration': 6.081},\n", + " {'text': 'on the system now you can install rastu',\n", + " 'start': 398.8,\n", + " 'duration': 5.6},\n", + " {'text': 'so here you have two choices you can',\n", + " 'start': 402.0,\n", + " 'duration': 5.28},\n", + " {'text': 'install roster with this ros humble',\n", + " 'start': 404.4,\n", + " 'duration': 7.76},\n", + " {'text': 'desktop or ros humble dash ros dash base',\n", + " 'start': 407.28,\n", + " 'duration': 7.359},\n", + " {'text': 'so browse base is actually sort of you',\n", + " 'start': 412.16,\n", + " 'duration': 3.84},\n", + " {'text': 'can see the bare bows just the',\n", + " 'start': 414.639,\n", + " 'duration': 2.721},\n", + " {'text': 'communication', 'start': 416.0, 'duration': 3.039},\n", + " {'text': \"the command line tools you don't have\",\n", + " 'start': 417.36,\n", + " 'duration': 4.16},\n", + " {'text': 'any graphical tools and utilities this',\n", + " 'start': 419.039,\n", + " 'duration': 5.121},\n", + " {'text': 'is what you would want to have in a',\n", + " 'start': 421.52,\n", + " 'duration': 4.239},\n", + " {'text': 'limited system for example on a',\n", + " 'start': 424.16,\n", + " 'duration': 3.599},\n", + " {'text': 'raspberry pi or if you have a computer',\n", + " 'start': 425.759,\n", + " 'duration': 4.401},\n", + " {'text': \"with very low resources or if you don't\",\n", + " 'start': 427.759,\n", + " 'duration': 5.041},\n", + " {'text': 'have a graphical interface for example',\n", + " 'start': 430.16,\n", + " 'duration': 4.4},\n", + " {'text': 'but here what we want is to have the',\n", + " 'start': 432.8,\n", + " 'duration': 5.119},\n", + " {'text': 'base plates also all the utilities some',\n", + " 'start': 434.56,\n", + " 'duration': 6.0},\n", + " {'text': 'demos some tutorials and some graphical',\n", + " 'start': 437.919,\n", + " 'duration': 4.961},\n", + " {'text': \"tools so we're gonna install\", 'start': 440.56, 'duration': 5.359},\n", + " {'text': 'this so you just do sudo apt install',\n", + " 'start': 442.88,\n", + " 'duration': 5.759},\n", + " {'text': 'rush handle desktop you press enter',\n", + " 'start': 445.919,\n", + " 'duration': 5.28},\n", + " {'text': \"and here well i've already installed it\",\n", + " 'start': 448.639,\n", + " 'duration': 4.721},\n", + " {'text': 'before for this tutorial but you will',\n", + " 'start': 451.199,\n", + " 'duration': 4.881},\n", + " {'text': 'see a lot of packages so maybe you will',\n", + " 'start': 453.36,\n", + " 'duration': 4.64},\n", + " {'text': 'have a few hundreds of packages for a',\n", + " 'start': 456.08,\n", + " 'duration': 4.08},\n", + " {'text': 'few hundreds of megabytes to download',\n", + " 'start': 458.0,\n", + " 'duration': 5.52},\n", + " {'text': 'and your few giga to be added to your',\n", + " 'start': 460.16,\n", + " 'duration': 5.2},\n", + " {'text': \"hard drive okay so that's gonna be a lot\",\n", + " 'start': 463.52,\n", + " 'duration': 3.92},\n", + " {'text': 'so you press yes and then you can wait',\n", + " 'start': 465.36,\n", + " 'duration': 4.48},\n", + " {'text': \"for a few minutes it's gonna depend of\",\n", + " 'start': 467.44,\n", + " 'duration': 4.159},\n", + " {'text': 'course on your internet connection speed',\n", + " 'start': 469.84,\n", + " 'duration': 4.16},\n", + " {'text': 'and the performance of your computer',\n", + " 'start': 471.599,\n", + " 'duration': 4.561},\n", + " {'text': 'and right once you have', 'start': 474.0, 'duration': 4.319},\n", + " {'text': 'successfully installed this then ros2 is',\n", + " 'start': 476.16,\n", + " 'duration': 4.319},\n", + " {'text': 'installed and just a quick note here is',\n", + " 'start': 478.319,\n", + " 'duration': 3.681},\n", + " {'text': 'that if you want to install any rost2',\n", + " 'start': 480.479,\n", + " 'duration': 4.56},\n", + " {'text': 'package in the future well this is very',\n", + " 'start': 482.0,\n", + " 'duration': 5.199},\n", + " {'text': 'simple because all the rows to package',\n", + " 'start': 485.039,\n", + " 'duration': 4.56},\n", + " {'text': 'for the humble distribution for example',\n", + " 'start': 487.199,\n", + " 'duration': 6.081},\n", + " {'text': 'will be ros humble dash something',\n", + " 'start': 489.599,\n", + " 'duration': 5.44},\n", + " {'text': 'so you will just need to run this',\n", + " 'start': 493.28,\n", + " 'duration': 5.52},\n", + " {'text': 'command sudo apt install ros humble dash',\n", + " 'start': 495.039,\n", + " 'duration': 5.84},\n", + " {'text': 'the name of the package', 'start': 498.8, 'duration': 5.44},\n", + " {'text': 'so this is quite easy now well ros is',\n", + " 'start': 500.879,\n", + " 'duration': 4.88},\n", + " {'text': 'installed', 'start': 504.24, 'duration': 4.0},\n", + " {'text': \"but we can't just use it like this we\",\n", + " 'start': 505.759,\n", + " 'duration': 3.44},\n", + " {'text': 'need to', 'start': 508.24, 'duration': 3.359},\n", + " {'text': 'set up the environment', 'start': 509.199, 'duration': 5.041},\n", + " {'text': \"okay because so let's clear this\",\n", + " 'start': 511.599,\n", + " 'duration': 5.841},\n", + " {'text': 'if i just do rust2 you will see that',\n", + " 'start': 514.24,\n", + " 'duration': 6.32},\n", + " {'text': 'rost2 command not found so to be able to',\n", + " 'start': 517.44,\n", + " 'duration': 5.12},\n", + " {'text': 'run rost2 first you need to install it',\n", + " 'start': 520.56,\n", + " 'duration': 3.44},\n", + " {'text': 'which is done and then you need to',\n", + " 'start': 522.56,\n", + " 'duration': 2.399},\n", + " {'text': 'source', 'start': 524.0, 'duration': 4.399},\n", + " {'text': 'a setup script here in every session or',\n", + " 'start': 524.959,\n", + " 'duration': 5.201},\n", + " {'text': 'every terminal where you want to use',\n", + " 'start': 528.399,\n", + " 'duration': 2.961},\n", + " {'text': 'roster', 'start': 530.16, 'duration': 5.6},\n", + " {'text': 'and so if we go to slash opt', 'start': 531.36, 'duration': 6.479},\n", + " {'text': 'you will see that this is where ros is',\n", + " 'start': 535.76,\n", + " 'duration': 4.16},\n", + " {'text': 'installed you can go to slash',\n", + " 'start': 537.839,\n", + " 'duration': 4.801},\n", + " {'text': 'so opt slash ros and then you will see',\n", + " 'start': 539.92,\n", + " 'duration': 3.68},\n", + " {'text': 'handle', 'start': 542.64, 'duration': 2.48},\n", + " {'text': 'this is the distribution we just',\n", + " 'start': 543.6,\n", + " 'duration': 3.239},\n", + " {'text': 'installed', 'start': 545.12, 'duration': 4.48},\n", + " {'text': 'so for us humble is actually rush to',\n", + " 'start': 546.839,\n", + " 'duration': 5.12},\n", + " {'text': 'humble okay and here you see we have a',\n", + " 'start': 549.6,\n", + " 'duration': 5.919},\n", + " {'text': 'setup.bash script and this is the script',\n", + " 'start': 551.959,\n", + " 'duration': 5.641},\n", + " {'text': 'that we need to source', 'start': 555.519, 'duration': 4.161},\n", + " {'text': 'here okay we need to source that so',\n", + " 'start': 557.6,\n", + " 'duration': 3.76},\n", + " {'text': \"let's go back to\", 'start': 559.68, 'duration': 4.0},\n", + " {'text': \"home directory and let's just source\",\n", + " 'start': 561.36,\n", + " 'duration': 3.12},\n", + " {'text': 'this', 'start': 563.68, 'duration': 3.279},\n", + " {'text': 'script', 'start': 564.48, 'duration': 2.479},\n", + " {'text': 'and now that this is sourced', 'start': 567.279, 'duration': 5.041},\n", + " {'text': 'look at that if i do rush to', 'start': 569.36, 'duration': 4.56},\n", + " {'text': 'now so we have', 'start': 572.32, 'duration': 4.24},\n", + " {'text': 'the help actually of the command',\n", + " 'start': 573.92,\n", + " 'duration': 4.479},\n", + " {'text': \"we don't have rows to command not found\",\n", + " 'start': 576.56,\n", + " 'duration': 5.04},\n", + " {'text': 'we have the help of the command okay',\n", + " 'start': 578.399,\n", + " 'duration': 5.281},\n", + " {'text': 'which means that this has been found and',\n", + " 'start': 581.6,\n", + " 'duration': 4.4},\n", + " {'text': 'rost2 is correctly installed and',\n", + " 'start': 583.68,\n", + " 'duration': 3.279},\n", + " {'text': 'set up', 'start': 586.0, 'duration': 2.8},\n", + " {'text': \"now the thing is let's say open new\",\n", + " 'start': 586.959,\n", + " 'duration': 3.761},\n", + " {'text': 'terminal', 'start': 588.8, 'duration': 2.96},\n", + " {'text': 'and i do', 'start': 590.72, 'duration': 3.36},\n", + " {'text': 'rush too once again i have the same',\n", + " 'start': 591.76,\n", + " 'duration': 5.68},\n", + " {'text': 'problem so i need to set up', 'start': 594.08, 'duration': 5.04},\n", + " {'text': 'the environment', 'start': 597.44, 'duration': 3.36},\n", + " {'text': 'and now it works', 'start': 599.12, 'duration': 3.44},\n", + " {'text': 'okay so i will need to set up the',\n", + " 'start': 600.8,\n", + " 'duration': 4.719},\n", + " {'text': 'environment for each terminal i use or',\n", + " 'start': 602.56,\n", + " 'duration': 5.279},\n", + " {'text': 'if you connect with ssh for example you',\n", + " 'start': 605.519,\n", + " 'duration': 4.081},\n", + " {'text': 'will need to set up the environment for',\n", + " 'start': 607.839,\n", + " 'duration': 4.401},\n", + " {'text': \"each ssh session and so that's not\",\n", + " 'start': 609.6,\n", + " 'duration': 4.239},\n", + " {'text': 'really convenient all right so what',\n", + " 'start': 612.24,\n", + " 'duration': 3.68},\n", + " {'text': \"we're going to do instead is we're going\",\n", + " 'start': 613.839,\n", + " 'duration': 3.521},\n", + " {'text': 'to add', 'start': 615.92, 'duration': 5.44},\n", + " {'text': 'this line to the bash rc file', 'start': 617.36, 'duration': 6.8},\n", + " {'text': 'in our profile here for the user so that',\n", + " 'start': 621.36,\n", + " 'duration': 4.88},\n", + " {'text': 'this line is going to be executed every',\n", + " 'start': 624.16,\n", + " 'duration': 4.72},\n", + " {'text': 'time we open a new terminal or session',\n", + " 'start': 626.24,\n", + " 'duration': 5.68},\n", + " {'text': 'okay so to do that we are going to use',\n", + " 'start': 628.88,\n", + " 'duration': 4.16},\n", + " {'text': 'jedit', 'start': 631.92, 'duration': 2.56},\n", + " {'text': 'and then you can do', 'start': 633.04, 'duration': 3.44},\n", + " {'text': 'bash see so', 'start': 634.48, 'duration': 3.28},\n", + " {'text': 'tilde', 'start': 636.48, 'duration': 4.24},\n", + " {'text': 'to go to your home directory slash dot',\n", + " 'start': 637.76,\n", + " 'duration': 5.759},\n", + " {'text': 'assi so this is a hidden file press',\n", + " 'start': 640.72,\n", + " 'duration': 5.52},\n", + " {'text': 'enter and you can see we have already a',\n", + " 'start': 643.519,\n", + " 'duration': 4.961},\n", + " {'text': 'lot of lines and all this stuff is going',\n", + " 'start': 646.24,\n", + " 'duration': 3.92},\n", + " {'text': 'to be executed when', 'start': 648.48, 'duration': 4.96},\n", + " {'text': 'you open a new session or a new terminal',\n", + " 'start': 650.16,\n", + " 'duration': 5.679},\n", + " {'text': 'so you go to the very end of the file',\n", + " 'start': 653.44,\n", + " 'duration': 3.36},\n", + " {'text': 'and', 'start': 655.839, 'duration': 2.961},\n", + " {'text': \"let's add a new line here and what do we\",\n", + " 'start': 656.8,\n", + " 'duration': 4.64},\n", + " {'text': 'put we put just this one', 'start': 658.8, 'duration': 3.68},\n", + " {'text': 'okay', 'start': 661.44, 'duration': 3.44},\n", + " {'text': 'source slash property slash ross slash',\n", + " 'start': 662.48,\n", + " 'duration': 5.2},\n", + " {'text': 'humble slash setup dot bash', 'start': 664.88, 'duration': 4.56},\n", + " {'text': \"let's save the file\", 'start': 667.68, 'duration': 4.48},\n", + " {'text': \"let's quit and let's just quit all the\",\n", + " 'start': 669.44,\n", + " 'duration': 5.12},\n", + " {'text': \"terminals that we have let's open a new\",\n", + " 'start': 672.16,\n", + " 'duration': 3.52},\n", + " {'text': 'terminal', 'start': 674.56, 'duration': 2.88},\n", + " {'text': 'and when you open the terminal',\n", + " 'start': 675.68,\n", + " 'duration': 4.159},\n", + " {'text': \"this line will be executed because it's\",\n", + " 'start': 677.44,\n", + " 'duration': 4.959},\n", + " {'text': 'in the bash ac now i can do rows too and',\n", + " 'start': 679.839,\n", + " 'duration': 4.961},\n", + " {'text': 'you can see now it is working so when',\n", + " 'start': 682.399,\n", + " 'duration': 5.12},\n", + " {'text': 'you have rows to with usage rows to and',\n", + " 'start': 684.8,\n", + " 'duration': 4.8},\n", + " {'text': 'the help of the command it means that',\n", + " 'start': 687.519,\n", + " 'duration': 4.0},\n", + " {'text': 'ros 2 is correctly installed and', 'start': 689.6, 'duration': 4.4},\n", + " {'text': 'configured and congratulations you are',\n", + " 'start': 691.519,\n", + " 'duration': 6.0},\n", + " {'text': 'now ready to start using rost2 alright',\n", + " 'start': 694.0,\n", + " 'duration': 5.6},\n", + " {'text': \"that's the end of this episode if you\",\n", + " 'start': 697.519,\n", + " 'duration': 4.401},\n", + " {'text': 'found it useful you will definitely like',\n", + " 'start': 699.6,\n", + " 'duration': 4.88},\n", + " {'text': 'my full course on ras2 for beginners',\n", + " 'start': 701.92,\n", + " 'duration': 4.72},\n", + " {'text': 'this course contains more than 10 hours',\n", + " 'start': 704.48,\n", + " 'duration': 4.32},\n", + " {'text': 'of content and will teach you everything',\n", + " 'start': 706.64,\n", + " 'duration': 4.16},\n", + " {'text': 'you need to create complete roster',\n", + " 'start': 708.8,\n", + " 'duration': 4.159},\n", + " {'text': 'applications you can find the link in',\n", + " 'start': 710.8,\n", + " 'duration': 4.24},\n", + " {'text': 'the description thank you for watching',\n", + " 'start': 712.959,\n", + " 'duration': 3.601},\n", + " {'text': 'see you in the course all in the next',\n", + " 'start': 715.04,\n", + " 'duration': 4.96},\n", + " {'text': 'tutorial of the series', 'start': 716.56, 'duration': 3.44}]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/requirements.txt b/requirements.txt index 099020b..1ae7644 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,162 @@ -# Core dependencies +aiofiles +aiohappyeyeballs +aiohttp +aiosignal +aiosqlite +annotated-types +anyio +appnope +asttokens +async-timeout +attrs +beautifulsoup4 +certifi +charset-normalizer clearml +clearml-agent +click +colorama +comm +contourpy +Crawl4AI +cycler +debugpy +decorator +distro +dnspython +exceptiongroup +executing +fake-http-header +fastapi +ffmpy +filelock +fonttools +frozenlist +fsspec +furl +gitdb +GitPython +gradio +gradio_client +greenlet +grpcio +grpcio-tools +h11 +h2 +hpack +html2text +httpcore +httpx +huggingface-hub +hyperframe +idna +importlib_metadata +importlib_resources +iniconfig +ipykernel +ipython +jedi +Jinja2 +jiter +joblib +jsonschema +jsonschema-specifications +jupyter_client +jupyter_core +kiwisolver +litellm +loguru +lxml +markdown-it-py +MarkupSafe +matplotlib +matplotlib-inline +mdurl +mockito +mpmath +multidict +nest-asyncio +networkx +numpy +openai +orderedmultidict +orjson +packaging +pandas +parso +pathlib2 +pexpect +pillow +platformdirs +playwright +pluggy +portalocker +prompt_toolkit +propcache +protobuf +psutil +ptyprocess +pure_eval +pydantic +pydantic_core +pydub +pyee +Pygments +PyJWT pymongo +pyparsing +pytest +pytest-mockito +python-dateutil +python-dotenv +python-multipart +pytz +PyYAML +pyzmq qdrant-client -gradio +rank-bm25 +referencing +regex +requests +rich +rpds-py +ruff +safetensors +scikit-learn +scipy +semantic-version +sentence-transformers +shellingham +six +smmap +sniffio +snowballstemmer +soupsieve +stack-data +starlette +sympy +tf-playwright-stealth +threadpoolctl +tiktoken +tokenizers +tomli +tomlkit torch +tornado +tqdm +traitlets transformers -sentence-transformers - -# ETL dependencies -gitpython -beautifulsoup4 -requests -python-dotenv - -# Utility packages -numpy -pandas -tqdm \ No newline at end of file +typer +typing_extensions +tzdata +urllib3 +uvicorn +wcwidth +websockets +xxhash +yarl +zipp +jupyter +PyGithub +google-api-python-client +youtube-transcript-api diff --git a/run_pipeline.py b/run_pipeline.py new file mode 100644 index 0000000..e057e8e --- /dev/null +++ b/run_pipeline.py @@ -0,0 +1,13 @@ +import sys +from pathlib import Path +from clearml import PipelineDecorator + +app_path = str(Path(__file__).parent / "app") +if app_path not in sys.path: + sys.path.append(app_path) + +from app.pipelines.clearml_etl_pipeline import etl_pipeline_logic + +if __name__ == "__main__": + PipelineDecorator.run_locally() + etl_pipeline_logic() \ No newline at end of file diff --git a/src/etl/config.py b/src/etl/config.py deleted file mode 100644 index f8444db..0000000 --- a/src/etl/config.py +++ /dev/null @@ -1,15 +0,0 @@ -from clearml import Task -from pymongo import MongoClient -import os -# from dotenv import load_dotenv - -# load_dotenv() - -def init_clearml(): - task = Task.init(project_name="ROS2-RAG", task_name="ETL-Pipeline") - return task - -def get_mongo_client(): - client = MongoClient(os.getenv('MONGODB_URI', 'mongodb://localhost:27017/')) - db = client['ros2_rag'] - return db \ No newline at end of file